예제 14 풀이 합병정렬 알고리즘에서 레코드의 저장 횟수를 기준으로 할 때 시간복잡도는 대략 T(n) = 2n log n이 됨을 증명하기
알고리즘 2.2 문제) n개의 원소를 비내림차순으로 정렬 입력) 양의 정수 n, 배열 S (인덱스는 1부터 n까지) 출력) 원소를 비내림차순으로 정렬한 배열 S
void mergesort ( int n, keytype S[] ) {
if ( n > 1 ) {
const int h = └n/2┘, m = n - h;
keytype U[1...h], V[1...m];
copy S[1] through S[h] to U[1] through U[h];
copy S[h+1] through S[n] to V[1] through V[m];
mergesort(h,U);
mergesort(m,V);
merge(h,m,U,V,S);
}
}
=> mergesort 함수는 n을 반으로 나누고, 이를 재귀적으로 정렬한다. n의 크기가 1이 될 때까지 계속해서 반으로 나누기 때문에 재귀 호출의 깊이는 log n이다. merge 함수는 두 개의 정렬된 배열을 합쳐서 하나의 정렬된 배열을 만든다. 이때 레코드를 임시 배열에 복사하고, 다시 원래 배열에 복사하는 두 번의 복사 작업이 필요하므로 레코드의 저장 횟수는 최대 2n번이 된다. mergesort 함수의 시간복잡도는 재귀 호출 횟수인 log n과 merge 함수의 레코드 저장 횟수인 2n을 곱하여 2n log n이 된다. 따라서 T(n) = 2n log n으로 표현할 수 있다.
알고리즘 2.4 문제) n개의 원소를 비내림차순으로 정렬 입력) 양의 정수 n, 배열 S (인덱스는 1부터 n까지) 출력) 원소를 비내림차순으로 정렬한 배열 S
void mergesort2 ( index low, index high ) {
index mid;
if ( low < high ) {
mid = └(low + high)/2┘;
mergesort2(low,mid);
mergesort2(mid+1,high);
merge2(low,mid,high);
}
}
=> mergesort2 함수는 배열의 첫 인덱스와 끝 인덱스를 인자로 받는다. 배열을 반으로 나누고, 재귀적으로 호출하여 정렬한다. 재귀 호출의 깊이는 log n이 되며, 각 단계에서 merge2 함수가 호출된다. merge2 함수는 두 개의 정렬된 배열을 합쳐서 하나의 정렬된 배열을 만든다. 이때 레코드를 임시 배열에 복사하고, 다시 원래 배열에 복사하는 두 번의 복사 작업이 필요하므로 레코드의 저장 횟수는 최대 2n번이 된다. 따라서 mergesort2 함수의 시간복잡도는 재귀 호출 횟수인 log n과 merge2 함수의 레코드 저장 횟수인 2n을 곱하여 2n log n이 된다. 따라서 T(n) = 2n log n으로 표현할 수 있다.