2 minute read

합병정렬 Merge Sort

✏️개념

  • 전체 원소를 담은 리스트를 작은 리스트 단위로 분할한 뒤에 다시 합치는 정렬

  • 퀵 정렬은 피벗 값에 따라 최악의 경우 시간복잡도가 N^2이 될 수도 있지만, 병합정렬은 정확히 반씩 쪼개기 때문에 N*LogN을 보장한다.

  • 퀵 정렬과 마찬가지로 분할정복 알고리즘이며, 퀵 정렬과 다르게 피벗 값이 없고 항상 반으로 나눈다.

fail to bring

3 7 8 1 5 9 6 10 2 4

  • 과정

    3 7 8 1 5 9 6 10 2 4                // 분할
    3 7 8 1 5 / 9 6 10 2 4
    3 7 8 / 1 5 / 9 6 10 / 2 4
    3 7 / 8 / 1 / 5 / 9 6 / 10 / 2 / 4
    3 / 7 / 8 / 1 / 5 / 9 / 6 / 10 / 2 / 4
    3 7 / 8 / 1 5 / 6 9 / 10 / 2 4      // 합병
    3 7 8 / 1 5 / 6 9 10 / 2 4
    1 3 5 7 8 / 2 4 6 9 10
    1 2 3 4 5 6 7 8 9 10     
    
  • 높이 LogN, 너비 N 이므로 N*LogN 이 보장된다. 퀵정렬보다 빠르다고 할 수는 없지만 이 시간복잡도가 안전하게 보장된다는 것이 특징이다.

✏️구현

    #include<iostream>
    using namespace std;

    int main(void){
        int data = {1, 3, 2, 5, 4, 7, 6, 8, 10};
        int size = 9;
        int middle = (0 + size-1)/2; 

        mergeSort(data, 0, size-1);

        return 0;
    }

    void merge(int *arr, int start, int mid, int end){
        int len = arr.length();
        int* newArr = new int[len];     // 정렬되는 수들이 들어갈 배열
        int i = start;
        int j = mid + 1;
        int k = start;      // 사실상 새로운 정렬된 리스트에서 인덱스가 i와 같기 때문

        // 작은 순서대로 리스트에 삽입
        while(i <= mid && j <= end){
            if(arr[i] >= arr[j]){
                newArr[k++] = arr[j++];
            }
            else{
                newArr[k++] = arr[i++];
            }

        }

        // i혹은j 둘 중 하나가 끝난경우 남은 값을 리스트에 모두 넣어줌
        if(i > mid){
            while(j <= end){
                newArr[k++] = arr[j++];
            }
        }
        else{
            while(i <= mid){
                newArr[k++] = arr[i++];
            }
        }

        // 정렬된 배열을 전달받은 배열에 복사
        for(int t = start; t <= end; t++){
            arr[t] = newArr[t];
        }

        delete[]newArr;
    }

    void mergeSort(int* arr, int start, int end){
        if(start < end){
            int middle = (start + end)/2;
            mergeSort(arr, start, middle);
            mergeSort(arr, middle + 1, end);
            merge(arr, start, middle, end);
        }
    }

✏️시간복잡도 / BigO

  • O(N*LogN)

  • 기존의 데이터를 담을 추가적인 배열 공간이 필요하다는 점에서 메모리 활용이 비효율적일 수 있다.