안정적인 정렬에서 최악의 경우 ?


35

안정적인 정렬 알고리즘 대신 최악의 경우 를 제공하는 좋은 리소스를 찾는 데 문제가 있습니다. 누구든지 좋은 자원을 알고 있습니까?O(nlnn)

단지 상기시켜주는 것은 전달 된 배열을 사용하고 정렬 알고리즘은 일정한 여분의 공간 만 사용할 수 있다는 것을 의미합니다. 안정은 동일한 키를 가진 요소가 원래 배열에서와 동일한 순서로 정렬 된 배열로 나타남을 의미합니다.

예를 들어, 순진 병합 정렬은 최악의 경우 이고 안정적이지만 추가 공간을 사용합니다. 표준 퀵 정렬은 안정적으로 만들어 질 수 있지만, 최악의 경우 입니다. 힙 정렬이 있고 최악의 경우 이지만 안정적이지 않습니다. Wikipedia 에는 정렬 알고리즘에 어떤 단점이 있는지에 대한 훌륭한 차트가 있습니다. 세 가지 안정성 조건, 최악의 경우 을 모두 갖추고 있고 적절한 정렬 알고리즘이 나열되어 있지 않습니다 .O ( 없음 ) O ( N 2 ) O ( N LN N ) O ( N LN N )O(nlnn)O(n)O(n2)O(nlnn)O(nlnn)

Katajainen, Pasanen 및 Teuhola의 "Practical in-place mergesort" 라는 논문이 발견되었습니다.이 논문에서는 안정적인 mergesort 변형 이 최악의 경우 인 것으로 주장합니다 . 결과를 올바르게 이해 하면 배열 의 첫 번째 및 배열의 ​​후자 에 대해 (bottom-up?) mergesort를 재귀 적으로 사용하고 두 번째 를 병합하기위한 스크래치 공간으로 사용하십시오. 나는 아직도 이것을 읽고 있으며 결과를 올바르게 해석하고 있는지에 대한 더 많은 정보가 높이 평가됩니다.1O(nlnn) 114 11214

또한 안정적인 퀵 정렬이 있는 최악의 경우 에 관심이 있습니다 . 내가 이해 한 바에 따르면, 퀵 정렬을 최악의 경우 하려면 적절한 피벗선택 해야합니다 .O ( N LN N )O(nlnn)O(nlnn)

이것은 순전히 이론적 인 관심사이며 실질적인 적용은 없습니다. 이 세 가지 기능을 모두 갖춘 알고리즘을 알고 싶습니다.


SO에 비슷한 질문이 여기 질문에서 제공하는 참조 I을 제공하는 대답와 함께. 나는 이것이 더 명확한 설명, 더 많은 문헌, 그리고 운 좋게도 알고리즘에 대한 설명을 요구하면서 중복 질문이 아니라고 생각합니다.
user834

1
math.stackexchange.com 에서이 질문 을 참조하십시오 .
이토 쓰요시

QuickSort에서 피벗을 선택하는 다른 방법으로 안정성이 떨어지는 이유는 무엇입니까?
svick

@svick, QuickSort 최악의 경우 를 만드는 방법을 아는 유일한 방법 은 피벗을 무작위보다 지능적으로 선택하는 것입니다. 내가 그렇게 배운 방법은 중간 값 알고리즘을 사용하는 선택 알고리즘을 사용하여 안정성을 파괴하는 것입니다. 내가 놓친 부분이 있으면 알려주십시오. O(nlnn)
user834

@TsuyoshiIto, 이것이 대답하는 것을 고려하십시오. 또한 알고리즘에 대한 간단한 스케치를 제공 할 수 있다면 실제로 도움이 될 것이라고 생각합니다.
user834

답변:


6

위의 모든 알고리즘이 있으며 지난 30 년 동안 거의 모든 알고리즘이 개발되었습니다.

아마도 2008 년에 Kim과 Kutzner의 버전 (WikiSort)을 포함하여 Block sort 라는 알고리즘 클래스가 가장 좋을 것입니다. 또한 적응 적이므로 이미 정렬 된 목록의 경우 O (n) 비교로 수렴되는 거의 정렬 된 목록을 정렬하는 단계가 더 적습니다. C, C ++ 및 Java에서 구현을 찾을 수 있습니다. https://github.com/BonzaiThePenguin/WikiSort

Huang과 Langston (1989-1992)의 GrailSort 알고리즘 (블록 정렬)도 흥미 롭습니다.이 알고리즘은 실제로 여러 유형의 테스트 사례에서 WikiSort를 능가합니다. https://github.com/Mrrl/GrailSort 에서 C ++ 구현을 사용할 수 있습니다.


8

적절하고 안정적인 병합 병합을 작성할 수 있습니다. 자세한 내용은 이것을 참조 하십시오. 저자 자신의 말로 :

아름다운 곳-병합 알고리즘. 회전이 어떻게 작동하는지 이해하려면 반전 배열에서 테스트하십시오. 안정적인 정렬 방식으로 가장 빠르게 알려져 있습니다. 스택 폭발 위험이 없습니다. 비용 : 상대적으로 많은 움직임. 스택은 여전히 ​​비쌀 수 있습니다. 이것은 하위 배열을 '회전'시키는 스마트 인플레 이스 병합을 갖춘 병합 정렬입니다. 이 코드는 C ++ stl 라이브러리에서 복제되어 Java로 번역됩니다.

여기에 코드를 복사하지는 않지만 링크에서 또는 C ++ STL을 확인하여 찾을 수 있습니다. 여기서 무슨 일이 일어나고 있는지에 대한 자세한 설명을 제공하려면 알려주세요.


8
간단한 설명을 해 주시면 도움이 될 것입니다. 가 필요하지 않을 수도 있지만 또한, 참조 구현은 다른 추가 재귀 사용 위반하는 공간 요소, 공간 조건을 (우리가 얻을 가정 에 대한 변수는 비트 비어 있는). 아마도 참조 된 알고리즘을 반복적으로 만들 수는 있지만 진행 상황을 이해하는 데 어려움을 겪고 있습니다. 구현에서 사용하는 참조 용지가 있습니까? O ( 1 ) O ( LN N )O(lnn)O(1)O(lnn)
user834

Knuth는 TAoCP에서도이 문제를 해결합니다.
라파엘

여기서 인용 한 알고리즘은 최악의 경우 입니다. Cf. cplusplus.com/reference/algorithm/stable_sort (특히 사용 가능한 메모리가 충분하지 않을 때 실행 시간에 대한 주석) O(nln2n)
quintopia

1

실용적인 생각에 대한 긴 의견으로 이것을 받아보십시오. 이것은 귀하의 질문에 대한 답변이 아니지만이 파이썬 토론에 관심이 있으실 것 같습니다.

이것은 적당히 안정된 팀 소트라고 불리는 적응적이고 안정적 이며 자연스러운 머지 소 르트에 대해 설명합니다 . 그것은 많은 종류의 부분적으로 배열 된 배열 ( 필요한 비교 및 만큼 적음 에서 초자연적 인 성능을 가지고 있지만 무작위 배열에서 Python의 이전에 조정 된 샘플 정렬 하이브리드만큼 빠릅니다.N - 1lg(N!)N1

[...]

길이 A와 B의 인접한 런을 제자리에 병합하는 것은 매우 어렵습니다 . 그것을 할 수있는 이론적 구조는 알려져 있지만 실제 사용 하기에는 너무 어렵고 느립니다 . 그러나 임시 메모리가 min (A, B)와 같으면 쉽습니다.

출처 : bugs.python.org , 저자 : Tim Peters

따라서 Timsort는 안정적이고 적절한 최악의 시간 복잡성 병합 정렬에 비해 여전히 장점이있는 것처럼 보입니다 .O(nlogn)

또한 Timsort는 이미 정렬 된 어레이에서 성능이 우수합니다.

그래서 파이썬은 Timsort (일부 조정이있는 Mergesort입니다)를 사용하며 몇 년 전에 Java 구현을 살펴본 결과 Mergesort였습니다 (지금은 Timsort도 사용한다고 생각합니다).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.