특정 정렬 알고리즘이 다른 정렬 알고리즘보다 선호되는 사용 사례는 무엇입니까-병합 정렬 대 QuickSort 대 힙 정렬 대 '인트로 정렬'등?
크기, 데이터 구조 유형, 사용 가능한 메모리 및 캐시 및 CPU 성능에 따라 사용하는 데 권장되는 안내서가 있습니까?
특정 정렬 알고리즘이 다른 정렬 알고리즘보다 선호되는 사용 사례는 무엇입니까-병합 정렬 대 QuickSort 대 힙 정렬 대 '인트로 정렬'등?
크기, 데이터 구조 유형, 사용 가능한 메모리 및 캐시 및 CPU 성능에 따라 사용하는 데 권장되는 안내서가 있습니까?
답변:
첫째, 정의는 매우 중요하기 때문에 정의입니다. 안정적인 정렬 은 동일한 키로 요소를 재정렬하지 않도록 보장하는 것입니다.
추천 :
빠른 정렬 : 안정적인 정렬이 필요하지 않고 평균 사례 성능이 최악의 경우보다 중요합니다. 빠른 정렬은 평균 O (N log N), 최악의 경우 O (N ^ 2)입니다. 좋은 구현은 재귀를 위해 스택 공간 형태로 O (log N) 보조 기억 장치를 사용합니다.
정렬 정렬 : 안정적인 O (N log N) 정렬이 필요한 경우 이것이 유일한 옵션입니다. 그것의 유일한 단점은 O (N) 보조 공간을 사용하고 빠른 정렬보다 약간 큰 상수를 가지고 있다는 것입니다. 적절한 병합 정렬이 있지만 AFAIK는 모두 O (N log N)보다 안정적이거나 나쁘지 않습니다. 제자리에있는 O (N log N)조차도 평범한 기존 병합 정렬보다 상수가 훨씬 커서 유용한 알고리즘보다 이론적 호기심이 많습니다.
힙 정렬 : 안정적인 정렬이 필요하지 않고 평균 케이스 성능보다 최악의 케이스 성능에 더 관심이있는 경우. O (N log N)이어야하며 O (1) 보조 공간을 사용하므로 매우 큰 입력에서 예기치 않게 힙 또는 스택 공간이 부족하지 않습니다.
Introsort : 빠른 정렬의 O (N ^ 2) 최악의 경우를 피하기 위해 특정 재귀 깊이 후에 힙 정렬로 전환되는 빠른 정렬입니다. O (N log N) 성능을 보장하면서 빠른 정렬의 평균 사례를 얻으므로 거의 항상 일반 오래된 빠른 정렬보다 낫습니다. 아마도 이것 대신 힙 정렬을 사용하는 유일한 이유는 O (log N) 스택 공간이 실질적으로 중요한 메모리 제한 시스템에 있기 때문입니다.
삽입 정렬 : 빠른 정렬 또는 병합 정렬의 기본 사례를 포함하여 N이 작을 때. 이것은 O (N ^ 2)이지만 상수는 매우 작으며 안정적인 정렬입니다.
Bubble sort, selection sort : 빠르고 더러운 일을 할 때 어떤 이유로 든 표준 라이브러리의 정렬 알고리즘을 사용할 수 없습니다. 삽입 정렬에 비해 이러한 장점은 구현하기가 조금 더 쉽다는 것입니다.
비 비교 정렬 : 상당히 제한된 조건에서는 O (N log N) 장벽을 깨고 O (N)으로 정렬 할 수 있습니다. 시도해 볼 가치가있는 경우는 다음과 같습니다.
계수 정렬 : 범위가 제한된 정수를 정렬 할 때.
기수 정렬 : log (N)이 K보다 상당히 큰 경우 K는 기수의 수입니다.
버킷 정렬 : 입력이 대략 균일하게 분산 될 수 있습니다.
Quicksort 는 일반적으로 평균 속도가 가장 빠르지 만 최악의 최악의 동작이 있습니다. 따라서 나쁜 데이터를 제공하지 않으면 O(N^2)
이를 피해야합니다.
병합 정렬 은 추가 메모리를 사용하지만 특히 외부 정렬 (예 : 메모리에 맞지 않는 대용량 파일)에 적합합니다.
힙 정렬 은 제자리에서 정렬 할 수 있으며 최악의 2 차 동작은 없지만 대부분의 경우 평균은 빠른 정렬보다 느립니다.
제한된 범위의 정수만 관련되는 경우 일종의 기수 정렬을 사용하여 매우 빠르게 만들 수 있습니다.
99 %의 경우, 일반적으로 퀵 정렬을 기반으로하는 라이브러리 정렬에 적합합니다.
정렬 알고리즘에 대한 Wikipedia 페이지에는 훌륭한 비교 차트가 있습니다.
http://en.wikipedia.org/wiki/Sorting_algorithm#Comparison_of_algorithms
제공된 비교 / 애니메이션에 대한 링크가 고려하지 않는 것은 데이터 양이 사용 가능한 메모리를 초과 할 때입니다. 이 작업을 수행해야하는 경우 일반적으로 병합 및 힙 정렬의 변형을 다루는 "외부 정렬"을 읽으십시오.
http://corte.si/posts/code/visualisingsorting/index.html 및 http://corte.si/posts/code/timsort/index.html 에는 다양한 정렬 알고리즘을 비교 한 멋진 이미지가 있습니다.
@ dsimcha 쓴 : 계산 정렬 : 제한된 범위의 정수를 정렬 할 때
나는 그것을 다음과 같이 바꿀 것입니다 :
계수 정렬 : 양의 정수를 정렬 할 때 (비둘기 구멍으로 인해 0-정수. MAX_VALUE-2).
선형 시간에서 효율성 휴리스틱으로 최대 및 최소 값을 항상 얻을 수 있습니다.
또한 중간 배열에는 최소 n 개의 추가 공간이 필요하며 안정적입니다.
/**
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
(실제로 MAX_VALUE-2까지 허용하지만) 참조 : Java 배열의 최대 크기는?
또한 기수 정렬 복잡도가 단어 크기 w의 정수인 n 키에 대해 O (wn)라고 설명합니다. 때때로 w는 상수로 표시되는데, 이는 n을 정렬하기 위해 O (n log n) 비교를 수행하는 최상의 비교 기반 정렬 알고리즘보다 기수 정렬을 더 좋게 (충분히 큰 n) 만들 수있게합니다. 그러나 일반적으로 w는 상수로 간주 될 수 없습니다. 모든 n 키가 고유 한 경우 임의 액세스 시스템이 메모리에 키를 저장할 수 있으려면 w가 최소한 log n이어야하므로 시간이 가장 복잡합니다. (n log n). (wikipedia에서)