나누기 및 정복 알고리즘 – 왜 두 개 이상의 부분으로 나눠지지 않습니까?


33

quicksort 및 mergesort와 같은 나누기 및 정복 알고리즘에서 입력은 일반적으로 (적어도 소개 텍스트에서는) 개로 분할되고 개의 작은 데이터 세트는 재귀 적으로 처리됩니다. 두 개의 반쪽이 전체 데이터 세트를 처리하는 작업의 절반 미만을 차지하는 경우 문제를 더 빨리 해결할 수 있다는 것이 의미가 있습니다. 그러나 왜 데이터 세트를 세 부분으로 나누지 않겠습니까? 네? n ?

많은 하위 집합으로 데이터를 나누는 작업으로 가치가 없지만, 두 개의 하위 집합에서 멈추어야한다는 직감이 부족합니다.

또한 3-way 퀵 정렬에 대한 많은 참조를 보았습니다. 이것은 언제 더 빠릅니까? 실제로 무엇이 사용됩니까?


배열을 세 부분으로 나누는 quicksort와 유사한 알고리즘을 만들어보십시오.
gnasher729

답변:


49

두 개의 반쪽이 전체 데이터 세트를 처리하는 작업의 절반 미만을 차지하는 경우 문제를 더 빨리 해결할 수 있다는 것이 이해가됩니다.

이것이 분할 및 정복 알고리즘의 본질 이 아닙니다 . 일반적으로 요점은 알고리즘이 "전체 데이터 세트를 처리 할"수 없다는 것입니다. 대신, 두 개의 숫자 정렬과 같이 해결하기가 쉽지 않은 조각으로 나뉘고, 사소하게 해결되고 결과가 전체 데이터 세트에 대한 솔루션을 산출하는 방식으로 재결합됩니다.

그러나 데이터 세트를 세 부분으로 나누지 않는 이유는 무엇입니까? 네? 엔?

주로 두 개 이상의 부분으로 나누고 두 개 이상의 결과를 다시 결합하면 구현이 더 복잡해 지지만 알고리즘의 기본 (Big O) 특성은 변경되지 않습니다. 차이는 일정한 요소이며 속도가 느려질 수 있습니다. 둘 이상의 부분 집합을 나누고 재결합하면 추가 오버 헤드가 발생합니다.

예를 들어, 3 방향 병합 정렬을 수행하는 경우 재조합 단계에서 이제 각 요소에 대해 가장 큰 3 개의 요소를 찾아야합니다.이 경우 1 대신 2 개의 비교가 필요하므로 전체적으로 두 배의 비교가 수행됩니다. . 그 대신에 재귀 깊이를 ln (2) / ln (3) == 0.63만큼 줄이므로 스왑은 37 % 줄어들지 만 비교 (및 메모리 액세스)는 2 * 0.63 == 26 % 증가합니다. 그것이 좋은지 나쁜지는 하드웨어에서 더 비싼 것에 달려 있습니다.

또한 3-way 퀵 정렬에 대한 많은 참조를 보았습니다. 이것은 언제 더 빠릅니까?

퀵 정렬이중 피벗 변형은 동일한 수의 비교가 필요하지만 평균적으로 스왑이 평균 20 % 적다는 것이 입증되어 순 이익입니다.

실제로 무엇이 사용됩니까?

요즘 누구도 더 이상 자체 정렬 알고리즘을 프로그래밍하지 않습니다. 그들은 도서관에서 제공하는 것을 사용합니다. 예를 들어, Java 7 API는 실제로 이중 피벗 퀵 정렬을 사용합니다.

어떤 이유로 든 자체 정렬 알고리즘을 실제로 프로그래밍하는 사람들은 대부분의 경우 오류 가능성이 20 % 더 뛰어 나기 때문에 간단한 2-way 변형을 고수하는 경향이 있습니다. 지금까지 가장 중요한 성능 향상은 코드가 "작동하지 않음"에서 "작동 중"으로 바뀌는 경우입니다.


1
작은 참고 사항 : Java 7은 프리미티브를 정렬 할 때만 Dual-Pivot 퀵 정렬을 사용합니다 . 개체를 정렬하려면 Timsort를 사용합니다.
Bakuriu

1
"현재는 누구도 더 이상 자체 정렬 알고리즘을 프로그래밍하지 않습니다."및 (더 중요한 것은 "중요 : 가장 중요한 성능 개선은 코드가"작동하지 않음 "에서"작동 중 "으로 바뀌는 경우입니다." 그러나 예를 들어 데이터 세트를 많은 부분으로 나누면 오버 헤드가 여전히 사소한 지 알고 싶습니다. 그렇게 발생함에 따라, 다른 사람이 있습니다 bealto.com/gpu-sorting_intro.html stackoverflow.com/questions/1415679/... devgurus.amd.com/thread/157159
AndrewJacksonZA

조금 느립니다. 왜 2 * 0.69 더 많은 비교가 필요한지 설명 할 수 있습니까? 0.69의 출처가 확실하지 않습니다.
jeebface

@jeebface oops, 그것은 오타였습니다 (현재 수정되었습니다). 0.63 (재귀 깊이 감소)이며 26 % 더 많은 결과가 나옵니다.
Michael Borgwardt

30

무의식적으로 말하면 중요하지 않습니다. 예를 들어, 이진 검색은 대략 log 2  n을 비교하고 3 진 검색은 대략 log 3  n을 비교합니다. 대수를 알고 있다면 log a  x = log b  x / log b  a이므로 이진 검색은 약 1 / log 3 삼항 검색보다 1.5 배 많은 비교. 이것은 아무도 대수 표기법으로 대수의 밑을 명시하지 않는 이유이기도합니다. 대수의 실제가 무엇이든 상관없이 주어진 염기의 대수에서 항상 일정한 요소입니다. 따라서 문제를 더 많은 부분 집합으로 나누는 것은 시간 복잡성을 개선하지 않으며 실제로는 더 복잡한 논리를 능가하기에 충분하지 않습니다. 실제로 이러한 복잡성은 실제 성능에 부정적인 영향을 미쳐 캐시 압력을 높이거나 미세 최적화를 실현하기 어렵게 만듭니다.

반면, 일부 나무가 많은 데이터 구조는 일반적으로 다른 이유로 높은 분기 요소 (3보다 크거나 32 이상)를 사용합니다. 메모리 계층 구조의 활용도를 향상시킵니다. RAM에 저장된 데이터 구조는 캐시를 더 잘 활용하고 디스크에 저장된 데이터 구조는 읽기 HDD-> RAM이 더 적습니다.


예. 이진 트리 구조 이상의 특정 응용 프로그램에 대한 옥트리를 찾습니다.
daaxix

@daaxix btree가 더 일반적 일 것입니다.
Jules

4

2 개가 아니라 N으로 세분화되는 검색 / 정렬 알고리즘이 있습니다.

간단한 예는 O (1) 시간이 걸리는 해시 코딩으로 검색하는 것입니다.

해시 함수가 순서 유지 인 경우 O (N) 정렬 알고리즘을 만드는 데 사용할 수 있습니다. (어떤 정렬 알고리즘은 숫자가 결과에서 어디로 가야하는지 N 검색하는 것처럼 생각할 수 있습니다.)

근본적인 문제는 프로그램이 일부 데이터를 검사 한 후 다음과 같은 상태에 진입 할 때 몇 개의 다음 상태가 있으며 그 확률이 ​​얼마나 가까운가?

컴퓨터가 두 숫자를 비교 한 다음 점프하거나하지 않는 경우, 두 경로가 똑같이 가능성이있는 경우 프로그램 카운터는 각 경로에서 하나 이상의 비트 정보를 "인식"하므로 평균적으로 하나를 "배웠습니다" 비트. 문제가 M 비트를 배워야하는 경우 이진 결정을 사용하면 M 결정보다 적은 답을 얻을 수 없습니다. 예를 들어, 크기가 1024 인 정렬 된 테이블에서 숫자를 찾는 것은 10 개의 이진 결정보다 더 적은 수의 결과를 얻을 수는 없지만, 그보다 더 적은 수의 결과를 얻지 못하더라도 확실히 수행 할 수는 없습니다.

컴퓨터가 하나의 숫자를 가져 와서이를 색인으로 배열로 변환하면, 배열에있는 요소 수의 2를 로그까지 "학습"하고 일정한 시간에 수행합니다. 예를 들어, 1024 개의 항목으로 구성된 점프 테이블이있는 경우 거의 동일하게 해당 테이블을 통해 점프하면 10 비트가 "학습"됩니다. 이것이 해시 코딩의 기본 요령입니다. 이에 대한 정렬 예는 카드 한 벌을 정렬하는 방법입니다. 각 카드마다 52 개의 쓰레기통이 있습니다. 각 카드를 통에 넣은 다음 모두 들어 올리십시오. 세분화가 필요하지 않습니다.


1

이것은 분류뿐만 아니라 일반적인 나누기와 정복에 관한 질문이기 때문에 아무도 마스터 정리를

간단히 말해, 분할 및 정복 알고리즘의 실행 시간은 두 가지 상쇄 력에 의해 결정됩니다. 더 큰 문제를 작은 문제로 전환함으로써 얻는 이점과 더 많은 문제를 해결해야하는 비용. 알고리즘의 세부 사항에 따라 문제를 두 개 이상의 조각으로 나누기 위해 지불하거나 지불하지 않을 수 있습니다. 각 단계에서 동일한 수의 하위 문제로 나누고 각 단계에서 결과를 결합하는 시간의 복잡성을 알고 있다면 마스터 정리는 전체 알고리즘의 시간 복잡성을 알려줍니다.

카라 츠바 승산을위한 알고리즘의 자릿수를 통상의 승산 알고리즘 (N ^ 2) O 박동 (n은 O의 주행 시간 (3 N ^ log_2 3)을 달성하기 위해 3- 방향 분할 컨커 사용 번호).


마스터 정리에서 생성하는 하위 문제의 수는 유일한 요인이 아닙니다. 가라 쓰바와 사촌 Strassen에서는 실제로 일부 하위 문제의 솔루션을 스마트하게 통합함으로써 개선이 이루어 지므로 하위 문제에 대한 재귀 호출 횟수를 줄일 수 있습니다. 간단히 말해서, b마스터 정리에서 a올라가면 더 나빠질 수록 더 느리게 올라갈 것을 요구합니다 .
InformedA

-4

이진 특성으로 인해 컴퓨터는 2로 나누는 데 매우 효율적이며 3에서는 크게 나누지 않습니다. 먼저 2로 나눈 다음 3으로 나눈 다음 파트 중 하나를 2로 다시 나눕니다. 2를 3 나누기 위해서는 2로 나눌 수도 있습니다.

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