개발/Algorithm

[Sort]Merge Sort(합병 정렬)

grulsuitg 2022. 6. 21. 19:17

설명

  • 두개의 정렬된 리스트가 주어졌을 때 두 개의 리스트를 합치면서 정렬하는 방법
  • Divide and Conquer (분할정복) 알고리즘의 방법이다.

예제

Psuedo Code

MERGE_SORT(A, p, r) // A는 정렬할 List p,r은 처음과 끝 index
    if p < r 
        q = [(p + r) / 2] // 중간값을 찾아 divide and conquer
        MERGE_SORT(A, p, q) // List의 왼쪽 부분을 정렬
        MERGE_SORT(A, q+1, r) // List의 오른쪽 부분을 정렬
        MERGE(A, p, q, r) // 왼쪽과 오른쪽을 합치면서 정렬


MERGE(A, p, q, r)  //A는 정렬할 List p는 처음 index, r은 마지막 index, q는 중간 index
    n1 = q - p + 1 // p 부터 q 까지의 크기
    n2 = r - q // q + 1 부터 r까지의 크기
    let L[1 ... n1 + 1] and R[1 ... n2 + 1] be new arrays
    for i = 1 to n1
        L[i] = A[p + i - 1] // L 리스트를 A의 index p 부터 q 로 초기화
    for j = 1 to n2
        L[j] = A[q + j] // R 리스트를 A의 index q + 1 부터 r 까지로 초기화

       //한쪽리스트가 먼저 다 Merge 될 경우 나머지 List의 값들을 inf와 비교해 Merge하기 위함 
    L[n1 + 1] = inf
    R[n2 + 1] = inf


    i = 1
    j = 1
    // 왼쪽 리스트의 값과 오른쪽 리스트의 값을 비교해가며 정렬
    for k = p to r
        if L[i] <= R[j]
            A[k] = L[i]
            i = i + 1
          else
            A[k] = R[j]
            j = j + 1

시간 복잡도

  • 분할 단계
    연산 수행 X
  • 비교 단계
    Divide의 깊이 (Recursion 호출 횟수)  → \(log_2N\)
    각각의 깊이에서의 비교 횟수 → \(N\)
    즉, 환 호출의 깊이 만큼의 합병 단계 * 각 합병 단계의 비교 연산 = \(Nlog_2N\)
  • 이동 단계
    깊이 (Recursion 호출 횟수)  → \(O(log_2N)\)
    각각의 깊이에서 이동 횟수 →  \(2N\) 번
    즉, 순환 호출의 깊이 만큼의 합병 단계 * 각 합병 단계의 이동 연산 = \(2Nlog_2N\)
  • 종합
    \(Nlog_2N + 2Nlog_2N = O(Nlog_2N)\)

Best Case & Worst Case 모두 \(O(Nlog_2N)\) 의 시간 복잡도를 가진다.

 

장점 

  • 데이터의 민감하지 않다.
    → Best & Worst 의 시간 복잡도가 똑같다.

단점

  • 배열을 복사해 사용해야 한다
    → 메모리의 낭비가 있다.

참고 자료