안정적이며 시간 복잡도는 O (n)입니다. Quicksort 및 Mergesort와 같은 알고리즘보다 빠르지 만 사용 된 적이 거의 없습니다.
안정적이며 시간 복잡도는 O (n)입니다. Quicksort 및 Mergesort와 같은 알고리즘보다 빠르지 만 사용 된 적이 거의 없습니다.
답변:
기수 정렬과 달리 퀵 정렬은 보편적 인 반면 기수 정렬은 고정 길이 정수 키에만 유용합니다.
또한 O (f (n))은 K * f (n)의 순서를 의미하며, 여기서 K는 임의의 상수입니다. 기수 정렬의 경우이 K는 상당히 커집니다 (적어도 정렬 된 정수의 비트 수 순서). 한편 quicksort는 모든 정렬 알고리즘 중 가장 낮은 K 중 하나이며 n * log (n)의 평균 복잡도입니다. 따라서 실제 시나리오에서 퀵 정렬은 기수 정렬보다 훨씬 빠릅니다.
대부분의 정렬 알고리즘은 범용입니다. 비교 함수가 주어지면 무엇이든 작동하며 Quicksort 및 Heapsort와 같은 알고리즘은 O (1) 추가 메모리로 정렬합니다.
기수 정렬이 더 전문적입니다. 사전 식 순서의 특정 키가 필요합니다. 키의 가능한 각 기호마다 하나의 버킷이 필요하며 버킷에는 많은 레코드가 있어야합니다. (또는 가능한 모든 키 값을 담을 수있는 하나의 큰 버킷 배열이 필요합니다.) 기수 정렬을 수행하려면 더 많은 메모리가 필요할 수 있으며 임의로 사용할 수 있습니다. Quicksort와 같은 페이지 오류가 발생하여 캐시 누락이 발생하기 때문에 최신 컴퓨터에는 적합하지 않습니다.
마지막으로 사람들은 일반적으로 더 이상 자체 정렬 알고리즘을 작성하지 않습니다. 대부분의 언어에는 정렬 할 라이브러리 기능이 있으며 일반적으로 사용하는 것이 올바른 것입니다. 기수 정렬은 보편적으로 적용 할 수 없으며 일반적으로 실제 용도에 맞게 조정해야하며 추가 메모리를 많이 사용하므로 라이브러리 함수 나 템플릿에 넣기가 어렵습니다.
O(n^2)
로 인해 최악의 경우 메모리가 필요 n
합니다. 구현에서 테일 재귀 최적화를 사용 O(n)
하는 경우 올바른 파티션에 대한 호출에 추가 공간이 필요하지 않기 때문에 낮출 수 있습니다 . ( en.wikipedia.org/wiki/Quicksort#Space_complexity )
S(n) \in O(n)
기수로 정렬하기위한 공간, 즉 힙 또는 빠른 정렬과 같은 공간 만 있으면됩니다 .
n^2
더 이상 quicksort 에 대해서는 언급하지 않지만 O(log n)
...
정렬하는 키가 실제로 알려진 희소 범위의 정수인 경우는 거의 없습니다. 일반적으로 알파벳 필드 는 비교하지 않는 정렬을 지원 하는 것처럼 보이지만 실제 문자열은 알파벳 전체에 고르게 분포되어 있지 않으므로 이론적으로는 잘 작동하지 않습니다.
다른 경우에, 기준은 운영상으로 만 정의 됩니다 (두 개의 레코드가 주어지면 어느 것이 먼저 오는지를 결정할 수 있지만 분리 된 레코드의 규모가 '먼'정도인지 평가할 수는 없습니다). 따라서이 방법은 적용 할 수 없거나 생각보다 덜 적용 할 수 있거나 O (n * log (n))보다 빠르지 않습니다.
나는 항상 비교 기반 정렬보다 더 많이 사용하지만 다른 것보다 숫자와 더 잘 작동하는 이상한 공입니다. (문자열로 거의 작업하지 않으며 일반적으로 기수와 관련이 있습니다. 정렬은 중복을 걸러 내고 집합 교차점을 계산하는 데 다시 유용 할 수 있습니다. 사전 비교를하지 않습니다.
기본 예는 검색 또는 중간 분할의 일부로 지정된 차원에 따라 기수 정렬 포인트 또는 일치 지점, 깊이 정렬 조각을 감지하는 빠른 방법 또는 여러 루프에서 사용되는 인덱스 배열을 기수 정렬하여 캐시 친화적 인 액세스를 제공하는 것입니다 패턴 (메모리에서 앞뒤로 돌아 가지 않고 다시 돌아가서 동일한 메모리를 캐시 라인으로 다시로드하는 것). 적어도 내 도메인 (컴퓨터 그래픽)에는 고정 크기 32 비트 및 64 비트 숫자 키로 정렬하기위한 매우 넓은 응용 프로그램이 있습니다.
필자가 말하고 싶었던 것은 기수 정렬이 부동 소수점 숫자와 음수에서 작동 할 수 있지만 가능한 휴대용 FP 버전을 작성하는 것은 어렵다는 것입니다. 또한 O (n * K)이지만 K는 키 크기의 바이트 수 여야합니다 (예 : 버킷에 2 ^ 8 개의 항목이있는 경우 백만개의 32 비트 정수는 일반적으로 4 바이트 크기의 패스를 사용함) ). 메모리 액세스 패턴은 일반적으로 병렬 배열과 작은 버킷 배열이 필요하지만 (두 번째는 일반적으로 스택에 잘 맞을 수 있지만) 퀵 정렬보다 캐시 친화적 인 경향이 있습니다. QS는 5 천만 스왑을 수행하여 산발적 인 랜덤 액세스 패턴으로 백만 개의 정수 배열을 정렬 할 수 있습니다. 기수 정렬은 데이터를 캐시에 친화적 인 4 개의 선형 패스로 수행 할 수 있습니다.
그러나 작은 K로 부동 소수점과 함께 음수로 이것을 할 수 있다는 인식이 부족하면 기수 종류의 인기 부족에 크게 기여할 수 있습니다.
사람들이 왜 더 자주 사용하지 않는지에 대한 나의 의견은 일반적으로 숫자를 정렬하거나 검색 키로 사용할 필요가없는 많은 도메인과 관련이있을 수 있습니다. 그러나 내 개인적인 경험을 바탕으로 이전의 많은 동료들도 완벽하게 적합한 경우에 그것을 사용하지 않았으며 부분적으로 FP 및 부정적인 작업을 수행 할 수 있다는 것을 알지 못했기 때문에 사용하지 않았습니다. 따라서 숫자 유형에서만 작동하는 것 외에도 실제보다 덜 일반적으로 적용되는 것으로 생각됩니다 . 부동 소수점 숫자와 음의 정수에서 작동하지 않는다고 생각하면 거의 사용하지 않을 것입니다.
일부 벤치 마크 :
Sorting 10000000 elements 3 times...
mt_sort_int: {0.135 secs}
-- small result: [ 12 17 17 22 52 55 67 73 75 87 ]
mt_radix_sort: {0.228 secs}
-- small result: [ 12 17 17 22 52 55 67 73 75 87 ]
std::sort: {1.697 secs}
-- small result: [ 12 17 17 22 52 55 67 73 75 87 ]
qsort: {2.610 secs}
-- small result: [ 12 17 17 22 52 55 67 73 75 87 ]
그리고 그것은 내 순진한 구현입니다 ( mt_sort_int
기수 정렬이지만 키가 정수라고 가정 할 수있는 코드 분기가 더 빠름). 전문가가 작성한 표준 구현이 얼마나 빠를 지 상상해보십시오.
C ++의 실제 빠른 비교 기반보다 기수 정렬이 더 나쁘다는 것을 발견 한 유일한 경우 std::sort
는 32 개의 작은 요소에 대한 것이 었습니다.이 시점에서 나는 std::sort
힙 정렬 또는 삽입 정렬, 그 시점에서 내 구현은을 사용합니다 std::sort
.
또 다른 이유 : 요즘 정렬은 일반적으로 컴파일러 제공 정렬 논리에 연결된 사용자 제공 정렬 루틴으로 구현됩니다. 기수 정렬을 사용하면 정렬 루틴이 가변 길이의 여러 키에 작용할 때이 작업이 훨씬 더 복잡해지고 더 악화됩니다. (이름, 생년월일.)
현실에서는 실제로 한 번 기수 정렬을 구현했습니다.. 이것은 메모리가 제한되어 있던 옛날에 모든 데이터를 한 번에 메모리에 가져올 수 없었습니다. 이는 데이터에 대한 액세스 수가 O (n) 대 O (n log n)보다 훨씬 중요하다는 것을 의미했습니다. 각 레코드를 빈에 할당하는 데이터를 한 번 통과했습니다 (실제로 아무것도 이동하지 않는 레코드가 어떤 빈에 있는지 목록으로). 비어 있지 않은 빈마다 (내 정렬 키는 텍스트 였으므로 empty bins) 실제로 데이터를 메모리로 가져올 수 있는지 확인했습니다. 그렇다면 가져 와서 퀵 정렬을 사용하십시오. 그렇지 않은 경우, 저장소의 항목 만 포함하는 임시 파일을 빌드하고 루틴을 재귀 적으로 호출하십시오. (실제로 몇 개의 빈이 오버플로 될 것입니다.) 이로 인해 네트워크 저장소에 대한 2 개의 완전한 읽기와 1 개의 완전한 쓰기가 발생했으며이 중 10 %는 로컬 저장소에 대한 것입니다.
요즘 이러한 빅 데이터 문제는 다루기가 훨씬 어렵습니다. 아마 그런 것을 다시는 쓰지 않을 것입니다. (요즘 같은 데이터에 직면했다면 간단히 64 비트 OS를 지정하고 해당 편집기에서 스 래싱이 발생하면 RAM을 추가하십시오.)
모든 매개 변수가 모두 정수이고 1024 개 이상의 입력 매개 변수가 있으면 기수 정렬이 항상 더 빠릅니다.
왜?
Complexity of radix sort = max number of digits x number of input parameters.
Complexity of quick sort = log(number of input parameters) x number of input parameters
기수 정렬이 더 빠를 때
log(n)> max num of digits
Java의 최대 정수는 2147483647입니다. 길이는 10 자리입니다.
따라서 기수 정렬은 항상 더 빠릅니다.
log(n)> 10
따라서 기수 정렬은 항상 더 빠릅니다
n>1024