2011-11-29 5 views
22

많은 알고리즘은 merge algorithm을 사용하여 두 개의 서로 다른 정렬 된 배열을 단일 정렬 된 배열로 병합합니다. 예를 들어, 어레이메모리 적응 형 병합 알고리즘?

1 3 4 5 8 

2 6 7 9 

이러한 배열의 병합

1 2 3 4 5 6 7 8 9 

전통적으로 병합하는 두 가지 방법이있을 것 어레이를 것 입력으로서 주어진 정렬 된 배열 (연결된 목록을 병합하는 경우는 매우 다르다는 점에 유의하십시오). 첫째, 저장소에 임시 버퍼를 할당 한 다음 병합 결과를 임시 버퍼에 저장하여 작동하는 out-of-place 병합 알고리즘이 있습니다. 둘째, 두 배열이 같은 입력 배열의 일부인 경우 O (1) 보조 저장 공간 만 사용하고 두 개의 인접한 시퀀스를 하나의 정렬 된 시퀀스로 다시 배열하는 in-place merge algorithms이 있습니다. 이 두 가지 클래스의 알고리즘은 모두 O (n) 시간에 실행되지만 out-of-place 병합 알고리즘은 이러한 엄격한 메모리 요구 사항이 없으므로 훨씬 더 낮은 상수 계수를 갖는 경향이 있습니다.

제 질문은이 두 접근법을 "보간"할 수있는 알려진 병합 알고리즘이 있는지 여부입니다. 즉 알고리즘은 O (1)과 O (n) 메모리 사이의 어느 곳에서나 사용할 수 있지만 사용 가능한 메모리가 많을수록 더 빠르게 실행됩니다. 예를 들어, 알고리즘에 의해 수행 된 배열 읽기/쓰기의 절대 개수를 측정하려면 ng (s) + f (s) 형식의 런타임이있을 수 있습니다. 여기서 s는 사용할 수있는 공간 크기이고 g (s)와 f (s)는 이용 가능한 공간의 양으로부터 유도 할 수있는 함수이다. 이 함수의 장점은 주어진 메모리 제약 조건에서 가능한 한 가장 효율적인 방법으로 두 배열을 병합하려고 시도 할 수 있다는 것입니다. 시스템에서 사용할 수있는 메모리가 많을수록 메모리가 더 많이 사용되고 성능은 더 좋습니다 (이상적으로). .

더 정식으로 알고리즘은 다음과 같이 작동해야합니다. 입력으로 인접한 두 개의 정렬 된 범위로 구성된 배열 A가 주어진다면 배열의 요소를 배열 순서대로 정렬해야합니다. 알고리즘은 외부 공간을 사용할 수 있으며 모든 경우에 최악의 경우 O (n)이어야하지만 사용하기에 더 많은 양의 보조 공간이 주어지면 점진적으로 더 빠르게 실행해야합니다.

는 이런 종류의 알고리즘에 익숙한 사람이 (또는 하나의 설명을 찾아 볼 위치를 알아?)

가 가
+1

http://stackoverflow.com/questions/3156599/merge-two-sorted-parts-of-an-array-with-constant-memory-in-on-time – necromancer

+0

@. 그러나, 나는 이것이 내가 찾고있는 것이라고 생각하지 않는다.나는 이미 당신이 O (1) 여분의 공간에서 병합 할 수 있다는 것을 알고 있으며,이 질문은 당신이 그것을 줄 수있는 여유 공간이 점진적으로 향상되는 병합 알고리즘을 갖는 방법이 있다면 대부분 묻는다. 예를 들어, 500MB의 데이터에 100MB의 여유 공간이 있으면 500MB의 데이터에 대해 10MB가있는 경우보다 빠르게 병합됩니다. – templatetypedef

+0

입력과 출력은 무엇입니까? 즉, 입력 배열 중 하나 또는 별도의 배열에 쓰고 있습니까? (필자는 후자라면이 문제가 아니기 때문에 전자는 의심 스럽습니다.) – MSN

답변

10

는 "자사의 런타임 복잡성 따라 적어도 문서에 따르면, in-place merge function in SGI STL 적응하고 얼마나 많은 메모리를 사용할 수 있는가? " 물론 소스 코드를 확인해 볼 수 있습니다.

+0

이것은 명확하게 작동하지만, 최악의 경우 O (n log n)까지 저하되며, 최악의 경우 O (n) 내부 병합 알고리즘이 존재합니다. 나는 O (n log n)이 여전히 아주 훌륭하지만, 이보다 더 좋은 무언가가 있기를 바라고 있습니다. – templatetypedef

2

EDIT : STL은 inplace_merge이며 사용 가능한 임시 버퍼의 크기에 맞춰 조정됩니다. 임시 버퍼가 적어도 하위 배열 중 하나만큼 큰 경우 O (N)입니다. 그렇지 않으면 병합을 두 개의 하위 병합과 반복으로 나눕니다. 분할은 O (log N)을 사용하여 회전 할 다른 하위 배열의 오른쪽 부분을 찾습니다 (2 진 검색).

따라서 사용 가능한 메모리 양에 따라 O (N)에서 O (N log N)로 변경됩니다. 링크에 대한 감사 agksmehx-

+0

이것은 확실히 작동하지만,'lhs '의 모든 항목이'rhs'의 가장 작은 항목보다 클 때 병적 인 행동을합니다. 예를 들어,'[5, 6, 7, 8, 9, 0, 1, 2, 3, 4]'와 같은 배열. 이 경우 알고리즘은 "rhs"에서 "temp"로'T' 항목을 복사하고,'lhs'을'T' 위치만큼 아래로 이동하고,'T' 항목을'temp'에서 새로 만든 공간으로 복사합니다. (sizeof (rhs) * sizeof (rhs))/T'가 배열 내에서 움직이고, 2 * (sizeof (rhs)/T)가 배열에서 temp와 back으로 이동한다.^2),'T == 1'이라면 알 수 있듯이 –

+0

@ 짐쉬 셸hel, 아니, 그것은'lhs'를 움직이지 않고'lhs'의 앞쪽에서'rhs'에 의해 남겨진 공간으로 복사하고 있습니다. 'lhs'에서 각 요소를 최대 두 번 복사하고 배열을 이동하지 않고 끝에있는 부분을 반복적으로 감싸는 것 'lhs'를 이동하면 N^2가됩니다. – MSN

+0

다른 알고리즘을 제거한 이유는 너무 복잡하고 실제 알고리즘은 단순한 것으로 밝혀 졌습니까? –

관련 문제