최소한의 비교로 두 개의 정렬 된 배열을 병합하는 알고리즘


24

크기가 nm 인 T 유형의 정렬 된 배열 a , b 가 제공 됩니다. 두 배열을 새 배열 (최대 크기 n + m)로 병합하는 알고리즘을 찾고 있습니다.

저렴한 비교 작업이 있으면 매우 간단합니다. 하나 또는 두 개의 배열이 완전히 이송 될 때까지 첫 번째 요소가 가장 낮은 배열에서 가져온 다음 나머지 요소를 추가하십시오. 이 같은 /programming/5958169/how-to-merge-two-sorted-arrays-into-a-sorted-array

그러나 두 요소를 비교할 때 상황이 변경되면 소스 배열에서 대상 배열로 요소를 복사하는 것보다 훨씬 비쌉니다 . 예를 들어 비교에 많은 비용이들 수있는 큰 임의 정밀도 정수 또는 문자열 배열이있을 수 있습니다. 배열을 만들고 요소를 복사하는 것이 자유롭고 비용이 드는 유일한 요소는 요소를 비교한다고 가정하십시오.

이 경우 두 배열 을 최소 수의 요소 비교와 병합하려고합니다 . 다음은 간단한 병합 알고리즘보다 훨씬 더 잘 수행 할 수있는 몇 가지 예입니다.

a = [1,2,3,4, ... 1000]
b = [1001,1002,1003,1004, ... 2000]

또는

a = [1,2,3,4, ... 1000]
b = [0,100,200, ... 1000]

간단한 병합 알고리즘이 최적의 경우가 있습니다.

a = [1,3,5,7,9,....,999]
b = [2,4,6,8,10,....,1000]

따라서 알고리즘은 배열이 인터리브되거나 적어도 크게 나 빠지지 않을 경우 이상적으로 우아하게 최대 n + m-1 비교를 수행하고 수행해야합니다.

크기 차이가 큰 목록의 경우 잘 수행해야 할 한 가지 방법은 이진 검색을 사용하여 작은 배열의 요소를 큰 배열에 삽입하는 것입니다. 그러나 두 목록의 크기가 같고 인터리브 된 경우에는 정상적으로 저하되지 않습니다.

요소에 사용 가능한 유일한 것은 (총) 순서 함수이므로 비교를 저렴하게 만드는 체계는 불가능합니다.

어떤 아이디어?

나는 Scala에서이 비트를 생각해 냈습니다 . 나는 그것이 비교의 수와 관련하여 최적이라고 생각하지만 그것을 증명할 수있는 능력을 벗어났습니다. 적어도 내가 문학에서 찾은 것보다 훨씬 간단합니다.

그리고 원래 게시물 이후로, 이것이 어떻게 작동하는지에 대한 블로그 게시물을 썼습니다 .


2
"간단한 병합 알고리즘"보다 적은 수의 비교를 수행 할 방법이 없습니다. 처음 언급 한 것과 같은 엣지 케이스를 처리하려고 시도 할 수 있지만 이는 평균 케이스를 악화시킵니다.
Mephy

5
@Mephy : 우리를 계몽하고 공식적으로 증명해주세요. 또는 할 수 없다면 댓글을 삭제 (또는 최소한 수정)하는 것이 좋습니다.
Doc Brown

4
@DocBrown 공식적인 증거가 있다면 의견이 아닌 답변을 줄 것입니다. 어쨌든, 선형보다 나은 솔루션을 찾으려면 최소한 선형 시간이 필요하기 때문에 그것은 매우 명백한 선형 문제입니다.
Mephy

4
@Mephy : 아래 답변을 읽는 데 시간이 걸리고 쓴 것에 대해 두 번 생각하는 것이 좋습니다.
Doc Brown

4
@Mephy 가장 명백한 것 ( "O (n ^ 2) 미만에서는 곱셈을 할 수 없음" ", "선택한 문을 변경하면 가격 을 얻을 수 있는 기회가 향상되지 않습니다 " ," 'O (n log n)보다 작게 정렬하지 않음', ..)이 잘못되었습니다. 예를 들어 짧은 목록에서 이진 검색 방법을 사용하면 평균 사례가 향상 될 수 있습니다.
Voo

답변:


31

일반적인 병합 정렬 알고리즘-일반적으로 병합 단계는 n + m -1 비교를 적용합니다. 여기서 하나의 목록은 크기가 n이고 다른 목록은 크기가 m입니다. 이 알고리즘을 사용하는 것이 두 개의 정렬 된 목록을 결합하는 가장 간단한 방법입니다.

비교가 너무 비싸면 두 가지 작업을 수행 할 수 있습니다. 비교 횟수를 최소화하거나 비교 비용을 최소화하십시오.

비교 비용의 최소화에 중점을 두겠습니다. 귀하와 귀하 만이 비교중인 데이터를 양자화 할 수 있는지 여부를 결정할 수 있습니다. 그것들을 양자화 할 수 있다면, 그것은 순서를 유지하는 해시 방법을 구현하는 형태입니다. 예를 들어 데이터를 이름으로 비교 한 다음 첫 번째 이름은 ... "Klaehn, Ruediger"라는 이름의 문자로 첫 번째를 가져 와서 비교하면 데이터 요소를 "Kl.Ru"로 줄이거 나 양을 정할 수 있습니다. "패커"에 순서 "Pa.Th"를 유지합니다. 이제 감소 된 값을 비교하여 더 저렴한 비교 알고리즘을 적용 할 수 있습니다. 그러나 다른 "Kl.Ru"를 찾으면 가치가 거의 다가오며 이제 이러한 요소를 비교하는 더 비싼 방법으로 전환 할 수 있습니다.

데이터에서이 양자화 된 값을 추출 할 수 있다면이를 비교하는 것보다 빠릅니다. 이것이 가장 먼저하는 일입니다. 먼저 양자화 된 값 또는 해시 된 값을 비교하십시오. 이 값은 한 번만 계산하면되므로 데이터 요소 작성시 계산할 수 있습니다.

또한 비교를 최소화하기 위해 다른 방법을 언급했습니다.

나는이 주제에 관한 10 페이지를 가지고있는 고전 책 TAOCP- Volume 3-Sorting and Searching, (pp.197-207, section 5.3.2)을 살펴 보았습니다. n + m-1 비교보다 빠른 알고리즘에 대한 두 가지 참조가 있습니다.

첫 번째는 황린 병합 알고리즘이 있고 두 번째는 Glenn K Manacher가 개선 한 것입니다. 둘 다 TAOCP와 인용 된 Christen 알고리즘은 길이 n과 m의 특수 조건에서 필요한 비교의 하한에 접근합니다. 목록 중.

Manacher의 알고리즘은 Journal of ACM Vol. 434-440 페이지의 26 번 3 번 : ""Han-Lin "병합 알고리즘에 대한 중요한 개선". m 개의 항목이있는 목록과 n 개의 항목이있는 목록은 길이가 다를 수 있지만 m <= n을 포함하는 요소의 수만큼 무시되어야합니다.

Hwang-Lin 알고리즘은 목록을 소규모 목록으로 분리하고 각 하위 목록의 첫 번째 요소를 비교하여 목록을 정렬하고 하위 목록의 일부 요소를 비교해야하는지 여부를 결정합니다. 첫 번째 목록이 두 번째 목록보다 작 으면 가능성이 높으므로 더 긴 목록의 연속 요소를 비교하지 않고 결과 목록으로 전송할 수 있습니다. 작은 ist의 첫 번째 요소가 분할 된 큰 목록의 첫 번째 요소보다 크면 하위 목록 앞에있는 모든 요소를 ​​비교하지 않고 복사 할 수 있습니다.

섹션 2에서 황과 린 (Vega, Frieze, Santha)의 병합 합병의 평균 사례 분석에서 HL- 알고리즘의 유사 코드를 찾을 수 있습니다. 내 설명보다 훨씬 낫습니다. 또한 비교가 적은 이유를 알 수 있습니다. 알고리즘은 이진 검색을 사용하여 색인을 찾고 더 짧은 목록에서 요소를 삽입 할 위치를 찾습니다.

마지막 예제와 같이 목록이 인터리브되지 않으면 대부분의 경우 더 작고 더 큰 목록이 있어야합니다. HL 알고리즘의 성능이 향상되기 시작할 때입니다.


이것에 대한 귀하의 의견에 감사드립니다-나는 대답을 확인하고 Knuth 가이 주제에 대해 10 페이지를 소비한다는 것을 알았습니다. 그런 다음 m 책장에서 JACM을 가져 와서 더 많이 보았습니다. 나는 대답을 향상시킬 것이다. -하향 투표가 필요 없습니다. 해시-(quantizer) 알고리즘은 간단한 아이디어이며 많은 데이터 세트에 적용 할 수 있지만 요청한 Guy만이 데이터에 적용 할 수 있는지 여부를 결정하는 유일한 사람입니다.
thepacker

4
답변을 개선 한 후, 귀하를 공감 한 모든 사람은 귀하를 다시 공감할 수있는 기회를 갖게됩니다. ;-)
Doc Brown

크기가 매우 다른 경우 표준 병합이 최적이 아니라는 점에 대해 +1입니다.
Florian F

1

두 배열에 N 및 M 요소, N ≥ M이 있고 모든 요소가 다르다고 가정합니다.

정렬 된 배열에 x의 요소 x와 M의 요소 y 또는 그 반대의 요소가 포함되어 있으면 x와 y를 비교해야합니다. 그렇지 않으면 배열이 속한 순서를 알 수 없습니다. (예를 들어, x와 y 사이에 요소가 없기 때문에 x <a <b <c <y라는 다른 요소 a, b, c의 체인은있을 수 없습니다. 따라서 x와 y는 비교되어야합니다. 직접.

N> M 인 경우 M의 각 요소 앞에 N이 오는 요소와 그 뒤에 N의 요소가있는 배열을 가질 수 있습니다. 즉, 비 결정적 정렬 알고리즘을 사용할 수있는 경우에도 2M 이상의 비교가 필요합니다. 비교할 숫자를 완벽하게 추측합니다. (즉, N이 크고 M이 1이라고 가정합니다. 이진 검색은 O (log2 N) 단계를 취합니다. 비 결정적 알고리즘은 두 번째 배열의 한 요소가 속하는 두 요소 사이를 추측하고 두 가지를 비교합니다. 추측을 확인하십시오).

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