주로 정렬 된 데이터에 가장 적합한 정렬 알고리즘은 무엇입니까?
주로 정렬 된 데이터에 가장 적합한 정렬 알고리즘은 무엇입니까?
답변:
애니메이션 GIF 를 보는 매우 과학적인 방법을 바탕으로 Insertion 및 Bubble 정렬이 좋은 후보라고 말합니다.
몇 개의 항목 만 => 삽입 열
항목은 대부분 이미 정렬되어 있습니다 => INSERTION SORT
최악의 시나리오에 대한 우려 => HEAP SORT
좋은 평균 사례 결과에 관심이 있음 => QUICKSORT
조밀 한 우주에서 아이템을 추출 함 => 버킷 소트
가능한 적은 코드를 작성하고 싶음 => 삽입 SORT
Timsort 는 " 다양한 부분 정렬 배열 (lg (N!) 비교가 필요하지 않고 N-1만큼 적음)의 초자연적 성능 "을 갖춘 "적응 형의 안정적이고 자연스러운 병합 정렬 "입니다. 파이썬 내장sort()
이 알고리즘을 한동안 사용해 왔으며 결과는 좋았습니다. 특히 실제 데이터 세트에서 발생하는 입력에서 부분적으로 정렬 된 하위 시퀀스를 감지하고 활용하도록 설계되었습니다. 실제로는 목록에서 항목을 바꾸는 것보다 비교가 훨씬 더 비싼 경우가 종종 있습니다. 일반적으로 포인터를 바꾸는 것만으로도 종종 팀 소트를 탁월한 선택으로 만듭니다. 그러나 비교가 항상 매우 저렴하다는 것을 알고 있다면 (예를 들어 32 비트 정수를 정렬하기 위해 장난감 프로그램 작성) 성능이 더 좋은 다른 알고리즘이 있습니다. timsort를 이용하는 가장 쉬운 방법은 물론 Python을 사용하는 것이지만 Python은 오픈 소스이므로 코드를 빌릴 수도 있습니다. 대안 적으로, 위의 설명은 자신의 구현을 작성하기에 충분한 세부 사항을 포함합니다.
lg(n!)
거의 정렬 된 배열의 비교 보다 훨씬 빠릅니다 O(n)
! | @behrooz : 없음 비교 정렬보다 더 나은의 평균 사건을 가질 수 O(n log n)
및lg(n!)
이다 O(n log n)
. 따라서 팀소 르트의 최악의 경우는 다른 비교 방식보다 최악의 경우가 아닙니다. 또한 가장 좋은 경우는 다른 비교 정렬보다 낫거나 같습니다.
다음과 같은 동작으로 삽입 정렬 :
k
슬롯의 각 요소 에 대해 1..n
먼저 여부를 확인하십시오 el[k] >= el[k-1]
. 그렇다면 다음 요소로 이동하십시오. (첫 번째 요소는 생략하십시오.)1..k-1
을 사용하여 삽입 위치를 확인한 다음 요소를 스쿠 트하십시오. (경우에만이 작업을 수행 할 수있는 k>T
곳 T
, 작은 일부 임계 값이 k
이 과잉이다.)이 방법은 비교 횟수를 최소화합니다.
내성적 인 정렬을 시도하십시오. http://en.wikipedia.org/wiki/Introsort
그것은 퀵 정렬을 기반으로하지만, 퀵 정렬이 거의 정렬 된 목록에 대해 최악의 행동을 피합니다.
이 정렬 알고리즘은 빠른 정렬이 최악의 모드로 전환되는 경우를 감지하고 힙 정렬 또는 병합 정렬로 전환하는 경우입니다. 거의 정렬되지 않은 파티션은 기본이 아닌 일부 파티션 방법으로 감지되며 작은 파티션은 삽입 정렬을 사용하여 처리됩니다.
더 많은 코드와 복잡성으로 인해 모든 주요 정렬 알고리즘을 최대한 활용할 수 있습니다. 또한 데이터의 모양에 관계없이 최악의 상황이 발생하지 않도록 보장 할 수 있습니다.
C ++ 프로그래머라면 std :: sort 알고리즘을 확인하십시오. 내부적으로 이미 내성 정렬을 사용하고있을 수 있습니다.
Splaysort 는 스플레이 트리를 기반으로하는 모호한 정렬 방법입니다 적응 이진 트리 유형 인 입니다. Splaysort는 부분적으로 정렬 된 데이터뿐만 아니라 부분적으로 역 분류 된 데이터 또는 실제로 어떤 종류의 기존 순서를 가진 데이터에도 적합합니다. 일반적인 경우에는 O (nlogn)이고 데이터가 어떤 방식으로 (정방향, 역방향, 오르간 파이프 등) 정렬 된 경우에는 O (n)입니다.
삽입 정렬에 비해 큰 장점은 데이터가 전혀 정렬되지 않은 경우 O (n ^ 2) 동작으로 되돌아 가지 않기 때문에 데이터를 사용하기 전에 데이터가 부분적으로 정렬되어 있는지 확실하게 알 필요는 없습니다 .
단점은 필요한 스플레이 트리 구조의 추가 공간 오버 헤드와 스플레이 트리를 구축하고 파괴하는 데 필요한 시간입니다. 그러나 데이터 크기와 예상되는 사전 정렬 된 양에 따라 오버 헤드가 속도를 높이는 데 가치가있을 수 있습니다.
splaysort에 용지가 연습 및 경험 - 소프트웨어에 출판되었다.
Dijkstra의 smoothsort는 이미 분류 된 데이터에 대한 훌륭한 정렬입니다. O (n lg n) 최악의 경우와 O (n) 최상의 경우에서 실행되는 힙 정렬 변형입니다. 나는 분석을 썼다 , 알고리즘을 경우에 당신이 어떻게 작동하는지 궁금.
Natural mergesort는 이것에 대한 또 다른 좋은 방법입니다. 입력을 여러 다른 정렬 된 범위의 연결로 취급 한 다음 merge 알고리즘을 사용하여 결합하여 작동하는 상향식 mergesort 변형입니다. 모든 입력 범위가 정렬 될 때까지이 과정을 반복합니다. 데이터가 이미 정렬되어 있고 O (n lg n) 최악의 경우 O (n) 시간에 실행됩니다. 매우 우아하지만 실제로 Timsort 또는 smoothsort와 같은 다른 적응 형 종류만큼 좋지 않습니다.
다른 사람들이 말했듯이 순진한 Quicksort를 조심하십시오. 정렬 된 또는 거의 정렬 된 데이터에 대해 O (N ^ 2) 성능을 가질 수 있습니다. 그럼에도 불구하고 피벗을 선택하기위한 적절한 알고리즘 (랜덤 또는 3의 중간 값 -Quicksort 의 피벗 선택 참조 )을 사용하면 Quicksort가 여전히 제대로 작동합니다.
일반적으로 삽입 정렬과 같은 알고리즘을 선택하는 데 어려움은 Quicksort가 실제로 더 빠를 정도로 데이터의 순서가 불충분 한 시점을 결정하는 데 있습니다.
실제 답변을 얻으려면 알고리즘을 코딩하고 대표 데이터 샘플에 대해 프로파일 링해야 할 수도 있기 때문에 여기에 모든 답변을하는 척하지는 않습니다. 그러나 나는 저녁 내내이 질문에 대해 생각 해 왔으며 여기까지 나에게 일어난 일이 있으며 어떤 것이 가장 잘 작동하는지 추측합니다.
N은 총 항목 수, M은 비 순차적 번호입니다.
버블 정렬은 모든 N 항목을 통과하는 2 * M + 1과 같은 것을 만들어야합니다. M이 매우 작 으면 (0, 1, 2?) 나는 이길 수 없을 것이라고 생각합니다.
M이 작 으면 (예 : log N보다 작음) 삽입 정렬의 평균 성능이 우수합니다. 그러나 내가 보지 못한 트릭이 없다면 최악의 성능이 나빠질 것입니다. (오른쪽? 주문의 마지막 항목이 먼저 오면 가능한 한 모든 단일 항목을 삽입해야 성능이 저하됩니다.) 더 신뢰할 수있는 정렬 알고리즘이 있다고 추측합니다. 경우, 그러나 나는 그것이 무엇인지 모른다.
M이 더 크면 (예 : log N보다 크거나 같음), 내성적 인 정렬이 거의 확실합니다.
이 모든 것의 예외 : 정렬되지 않은 요소를 미리 알고 있다면 가장 좋은 방법은 해당 항목을 꺼내고 내성 정렬을 사용하여 정렬 한 다음 정렬 된 두 목록을 하나의 정렬 된 목록으로 병합하는 것입니다. 어떤 항목이 고장 났는지 신속하게 파악할 수 있다면, 이것이 일반적인 해결책 일 것입니다. 그러나 나는 이것을하는 간단한 방법을 알아낼 수 없었습니다.
추가 생각 (야간) : M + 1 <N / M 인 경우 정렬 된 행에서 N / M 런을 찾은 목록을 스캔 한 다음 해당 런을 어느 한 방향으로 확장하여 범위를 벗어남을 찾을 수 있습니다. 주문 상품. 최대 2N 비교가 필요합니다. 그런 다음 정렬되지 않은 항목을 정렬하고 두 목록에서 정렬 된 병합을 수행 할 수 있습니다. 총 비교는 4N + M log2 (M)와 같은 것보다 작아야합니다. 이는 전문화되지 않은 정렬 루틴을 능가 할 것이라고 생각합니다. (더 이상 생각하면 : 생각보다 까다 롭지 만 여전히 가능하다고 생각합니다.)
이 질문에 대한 또 다른 해석은 많은 비정품 품목이있을 수 있지만 목록에 있어야하는 위치에 매우 가깝다는 것입니다. (정렬 된 목록으로 시작하여 다른 모든 항목을 그 다음에 오는 항목으로 바꾸는 것을 상상해보십시오.)이 경우 거품 정렬이 매우 잘 수행된다고 생각합니다. 패스 수가 항목에서 가장 멀리 떨어진 곳에 비례한다고 생각합니다. 입니다. 모든 주문 항목이 삽입을 트리거하기 때문에 삽입 정렬이 제대로 작동하지 않습니다. 내성적 인 종류 나 그와 비슷한 것이 잘 작동 할 것으로 생각됩니다.
정렬 알고리즘, 데이터 구조 또는 위의 링크가있는 것을 구현하기 위해 특정 구현이 필요한 경우 CodePlex 의 우수한 "데이터 구조 및 알고리즘" 프로젝트를 추천 해 주 시겠습니까?
휠을 재발 명하지 않고 필요한 모든 것을 갖추고 있습니다.
내 작은 곡물 알갱이.
대답 에서이 목적을위한이 훌륭한 정렬 알고리즘 모음에는 Gnome Sort 가 부족한 것 같습니다 .Gnome Sort 도 적합하며 아마도 최소한의 구현 노력이 필요합니다.
사전 정렬 된 데이터에는 매우 비효율적 인 QuickSort를 멀리하십시오. 삽입 정렬은 가능한 적은 값을 이동하여 거의 정렬 된 데이터를 잘 처리합니다.