ProgramingTip

연결 목록을 정렬 할 때 빠른 정렬 병합 정렬이 선호되는 이유

bestdevel 2020. 12. 5. 10:23
반응형

연결 목록을 정렬 할 때 빠른 정렬 병합 정렬이 선호되는 이유


포럼에서 다음을 읽었습니다.

병합은 연결 목록과 같은 변경 불가능한 데이터 구조에 매우 있습니다.

빠른 정렬은 일반적으로 데이터가 메모리에 저장 될 때 병합 정렬보다 빠 사용합니다. 그러나 데이터 세트가 방대하고 하드 드라이브와 같은 외부 장치에 저장되는 경우 병합이 속도에서 확실한 승자가됩니다. 외부 드라이브의 값 비싼 값을 최소화합니다.

연결 목록에서 작업 할 때 병합에는 일정량의 보조 기억 장치 만 필요합니다.

누군가가 위의 주장을 이해하도록 도울 수 있습니까? 거대한 연결 목록을 정렬하는 데 병합 정렬이 선호되는 이유는 무엇입니까? 그리고 지출 외장 드라이브에 대한 값 비싼 읽기를 어떻게 사용합니까? 기본적으로 큰 연결 목록을 정렬하기 위해 병합 병합을 선택하는 이유를 이해하고 싶습니다.


빠른 정렬은 내부 정렬에 적합합니다. 특히, 대부분의 작업은 배열에서 요소 쌍을 교환하는 관점에서 정의 할 수 있습니다. 그러나 그렇게하여 일반적으로 두 개의 개의 또는 배열을 "보행"합니다. 하나는 배열의 시작에서 시작하고 다른 하나는 끝에서 시작합니다. 그런 다음 둘 다 중간을 향해 작동합니다 (그리고 만나면 특정 파티션 단계가 완료됩니다). 파일은 주로 처음부터 끝까지 한 방향으로 읽기 때문에 비용이 많이 많이 사용됩니다. 끝에서 시작하여 뒤로하는 방법은 일반적으로 최강으로 비용이 많이 사용됩니다.

가장 단순한 화신에서 병합 정렬은 거의 반대입니다. 이를 구현하는 쉬운 방법은 데이터를 한 방향으로 만 보면 보는 것이지만 데이터를 두 개의 식별 조각으로 나누고 조각을 정렬 한 다음 다시 병합하는 것입니다.

연결 목록을 사용하면 (예를 들어) 하나의 연결 목록에서 요소를 번갈아 사용하고 링크를 조작하여 동일한 요소에서 두 개의 연결 목록을 만드는 것이 있습니다. 배열을 사용하면 원본 데이터만큼 큰 복사본을 만들려는 경우 교체 요소가 별도의 배열로 이동하도록 요소를 재배 열하는 것이 쉽지만 배열 사소하지 않습니다.

배열의 요소를 순서대로 데이터가있는 새 배열로 병합하면 배열과 병합 할 것이지만 데이터가 완전히 새로운 복사본을 만들지 않고 제자리에서 수행하는 것은 완전히 다른 이야기입니다. 연결 목록을 사용하면 두 소스 목록의 요소를 단일 대상 목록으로 병합하는 간단합니다. 다시 말하면 요소를 복사하지 않고 링크를 조작하기 만하면됩니다.

Quicksort를 사용하여 외부 병합 정렬을 위해 정렬 된 실행을 생성하는 경우 작동하지만 일반적으로 (결정적으로) 차선책입니다. 병합 생성을 최적화하는 것이 일반적으로 정렬 된 각 "실행"을 할 때 길이를 추가합니다. 메모리에 맞는 데이터를 읽고 실행은 사용 가능한 메모리의 크기로 제한됩니다.

일반적으로 훨씬 더 잘할 수 있습니다. 데이터 블록에서 읽기로 시작하지만 Quicksort를 사용하는 대신 힙을 빌드합니다. 그런 다음 힙의 각 항목을 정렬 된 "실행"파일에 쓸 때 입력 파일에서 다른 항목 을 읽습니다 . 방금 디스크에 쓴 항목보다 큰 기존 힙에 삽입하고 반복합니다.

더 작은 항목 (즉, 이미 존재하는 항목 속함)은 하단 유지하고 두 번째 힙에 빌드합니다. 첫 번째 힙이 비어 있고 두 번째 힙이 모든 메모리를 차지 항목하면 "실행"파일에 쓰기를 중단하고 새 파일에서 시작합니다.

어떤 순서에 따라 얼마나 재미가 있습니다. 최악의 경우 (입력이 역순으로 정렬 됨) 전혀 좋지 않습니다. 최상의 경우 (입력이 이미 정렬 됨) 입력을 통해 한 번의 실행으로 데이터를 "정렬"할 수 있습니다. 평균적인 경우 (무작위 순서로 입력) 각 정렬 된 실행의 길이를 약 두 배로 늘릴 수 있으며 일반적으로 속도가 20-25 % 향상됩니다 (비율은 사용 가능한 메모리보다 데이터가 얼마나 큰지에 따라 달라짐). ).


Quicksort는 배열 또는 배열 구조로 인덱싱 할 수 있는지 여부에 따라 진행됩니다. Quicksort를 이기기가 어렵습니다.

그러나 연결 목록에 직접 색인을 생성 할 수 없습니다. 즉, myList-link 된 목록 인 경우 myList[x]이러한 구문을 작성할 수 난 웬지 - 목록의 맨 위에서 시작하여 첫-th x-link를 따라야합니다 . Quicksort가 수행하는 모든 비교에 대해 두 번 수행하며 비용이 많이 소요됩니다.

디스크 마찬가지입니다. Quicksort는 비교하려는 모든 항목을 찾아서 읽어야합니다.

병합 정렬은 항목을 사용하여 로그 2 (N)를 통해 전달하기 때문에 더 빠 사용됩니다. 관련된 I / O가 훨씬 적고 어떤 목록의 링크를 따라가는 시간도 훨씬 적습니다.

Quicksort는 데이터가 메모리에 맞을 때 빠르며 직접 주소를 수 있습니다. 데이터가 메모리에 맞지 않고 항목에 도달하는 데 비용이 많이 많이 사용되는 경우 병합이 더 빠 사용합니다.

대용량 파일은 일반적으로 가능한 한 파일을 메모리에로드하고이를 Quicksort하고 임시 파일에 기록한 다음 전체 파일을 통과 할 때까지 반복합니다. 그 시점에서 각각의 블록이 정렬 된 몇 개의 블록이 있고 프로그램은 정렬 된 출력을 생성하기 위해 N-way 병합을 수행합니다.


빠른 정렬은 레코드를 목록 중간으로 이동합니다. 항목을 "X로 이동 비용 0에서 시작하여 한 번에 하나의 레코드를 반복해야합니다."

여러 개의 작은 목록으로 분할하고 목록의 항목 헤드 만 비교합니다.

많은 정렬 설정은 일반적으로 빠른 정렬에 필요한 반복보다 이동 비용이 많이 사용됩니다. 그러나 목록이 충분히 크거나 읽기가 비싸면 (디스크 에서처럼) 빠른 정렬이 반복되는 데 시간이 주요 배열이 있습니다.

참고 URL : https://stackoverflow.com/questions/5222730/why-is-merge-sort-preferred-over-quick-sort-for-sorting-linked-lists

반응형