Mergesort

2022. 9. 12. 17:09CS/자료구조, 알고리즘

이번 포스팅 내용은 Merge Sort 의 정확성을 증명해보는 것이다.

 

Divide and Conquer - 분할 정복

  • 입력을 나누어 더 작은 문제를 물고, 작은 문제들의 답을 조합해 전체 문제의 답을 만든다.
  • 아주 작은 문제는 어쨌거나 풀린다.

mergeSort는 분할 정복 기법을 사용한다. 문제를 더 작은 문제로 나누고, 답을 합칠 때(merge) 재귀가 사용된다.

 

 

 

위처럼 "이미 Sorted 된 두 배열을 합쳐(merge) Sorted 된 배열을 만들자" 가 이 알고리즘의 아이디어이다.

재귀라고 해서 따라 들어가지 않고, 바로 알 수 있도록 증명해보는 연습을 하는 것이다.

 

 

Recursive MergeSort

int sort(int a[], int n){
    if(n<=1)
        return 0;
    
    int h, b[n];
    h = n/2;
    // copy a[] to b[]
    sort(b, h);
    sort(b+h, n-h);
    // Merge two halves in b to a
    merge(a,b,n);
    return 0;
}
void merge(int a[], int b[], int n){
    int i=0, j=n/2, k=0;
    while(i<=n/2-1 && j<=n-1){
        if(b[i] < b[j]){
            a[k] = b[i]; i++;
        }else{
            a[k] = b[j]; j++;
        }
        k++;
    }

    if(i==n/2){
        while(j<=n-1){
            a[k] = b[j];
            k++; j++;
        }
    }
    else{
         while(i<=n/2-1){
            a[k] = b[i];
            k++; i++;
        }
    }
}

 

Proof By Induction

- 집합 조건을 깰 수 있는 코드는 없다. 

편의상 Sort 함수가 끝난 후 정렬된 배열을 b라 했을 때. (이름만 다른 것)

 

위처럼 집합 조건을 깰 수 있는 코드는 없다. 원소는 동일하다.

 

 

Base

n = 1 : 할 일이 없음

원소가 한 개 이므로 정렬을 할 대상이 아니다.

 

Step 

P(n-1) -> P(n) 임을 보이면 된다.

P(n-1) : n/2 일 때 sort() 가 성공 

P(n) : n 일 때 sort() 가 성공.

 

즉 재귀함수 호출이 끝난 후 b[0] < b[1] < .... < b[n/2-1] 이고, b[n/2] < b[n/2 + 1] < ..... <b[n-1] 이라면

n 일 때 sort() 함수가 성공한다 : 함수가 끝난 후 a[0] < a[1] < ...... < a[n-1] 이 성립한다.

이는 Merge 함수의 정확성에 의해, n 일 때 sort 가 성립한다.

 

merge 함수에서 집합조건을 깰 수 있는 코드는 없고, 정렬된 두 개의 배열을 정렬된 하나의 배열로 합치는 과정이므로 merge 는 참이다.

merge 함수의 시간복잡도 : O(N)

mergeSort 함수는 절반씩 나눠들어가므로, merge 과정을 logN 번 반복했다고 볼 수 있다.

따라서 mergeSort : T(N) : O(NlogN)

 

 

시간 복잡도 T(n)

 

merge 의 시간복잡도가 n . n이 logn 번 반복되므로, nlogn의 시간복잡도를 가진다.

'CS > 자료구조, 알고리즘' 카테고리의 다른 글

Prim 알고리즘 - 1  (0) 2022.09.18
Selection Sort 증명  (0) 2022.09.17
Binary Search 증명  (1) 2022.09.04
재귀 알고리즘의 정확성 증명  (0) 2022.09.03
Halting Problem (정지 문제)  (3) 2022.09.02