ABOUT ME

1st. CES 2nd. GBT

Today
Yesterday
Total
  • 5. 분할과 정복_병합정렬(Merge Sort)
    Algorithm 2019. 10. 4. 02:02

    #분할과 정복을 이용한 정렬

    -병합정렬

    -퀵정렬

     

    #분할과 정복 알고리즘

    1. 큰 문제를 작은 문제들로 나눈다.

    2. 단계1의 작은 문제들의 해를 재귀적으로 구한다.

    3. 단계2에서 구한 작은 문제들의 해를 이용하여 원래 문제의 해를 구한다.

     

    #병합정렬 알고리즘

    1. 주어진 크기가 n인 리스트를 크기가 n/2인 두 부분으로 나눈다.

    2. 크기가 n/2인 두 부분을 재귀적으로 정렬한다.

    3. 정렬된 두 부분을 하나로 병합한다.

     

    merge sort

     

     

    #구현

    #include <iostream>
    using namespace std;
    
    int* sorted;
    
    void mergesort(int a[], int first, int last);
    void merge(int a[], int first, int mid, int last);
    
    int main(){
        int size;
        cin>>size;
        sorted = new int[size]; //정렬 후 배열
        int* a = new int[size]; //정렬 전 배열
        for(int i=0; i<size; i++) cin>>a[i];
        
        mergesort(a,0,size-1);
       
       for(int i=0; i<size; i++) cout<<a[i]<<" ";
       delete[] a;
       return 0;
    }
    
    void mergesort(int a[], int first, int last){
        if(first<last){
            int mid=(first+last)/2;
            mergesort(a,first,mid);
            mergesort(a,mid+1,last);
            merge(a,first,mid,last);
        }
    }
    
    void merge(int a[], int first, int mid, int last){
    	int i=first; //왼쪽 배열의 첫 번째 인덱스
        int j=mid+1; //오른쪽 배열의 첫 번째 인덱스
        int k=first; //sorted의 첫 번째 인덱스
        
        //두 집합의 원소들 비교해서 더 작은 원소를 sorted 배열에 넣기
        while(i<=mid && j<=last){
            if(a[i]<=a[j]){
                sorted[k]=a[i];
                i++;
            }
            else{
                sorted[k]=a[j];
                j++;
            }
        }
        
        //남은 원소 sorted에 넣기
        if(i>mid){ //오른쪽 원소는 모두 sorted에 담긴 상태
            for(int t=j; t<=last; t++){
                sorted[k]=a[t];
                k++;
    		}
    	}
    	else{ //왼쪽 원소는 모두 sorted에 담긴 상태
            for(int t=i; t<=mid; t++){
                sorted[k]=a[t];
                k++;
            }
        }
    
        for(int t=first; t<=last; t++)
            a[t]=sorted[t];
    }
        

     

    #시간복잡도

    n=1인 경우 -> T(n) = 0 

    n>1인 경우 -> T(n) ≤ 2T(n/2) + n

                              ≤ 2( 2T(n/4) + n )+n

                              ...

                              ≤ (2^k)T(n/(2^k)) + k*n

    즉,  n=2^k 일 경우, T(n) ≤ n*T(1) + (log n)*n = 0 + n log n

     

    크기가 n인 배열을 분할할 때 원소가 하나가 될때까지 반으로 나누기 때문에 log n의 시간이 들고,

    병합할 때 while을 통해 모든 원소를 비교하기 때문에 n의 시간이 든다.

    따라서 병합정렬의 시간복잡도는 T(n): O(n log n) 이다.

     

    #병합정렬의 단점

    - 병합할 때 O(n) 추가적인 메모리가 필요하다.(in-place가 아니다)

    - O(log n)의 스택 메모리가 필요하다.

    'Algorithm' 카테고리의 다른 글

    댓글

Designed by Tistory.