1 minute read

병합정렬이란

  • 병합 정렬은 원소가 한 개가 될 때까지 계속해서 반으로 나누다가 다시 합쳐나가며 정렬을 하는 분할 정복 방식의 정렬이다.
  • 재귀적인 구조로 구현할 수 있고, 폰 노이만이 설계한 정렬이다.


병합정렬 코드

코드는 원소가 1개가 될때까지 재귀적으로 _merge_sort를 호출하다가 원소가 1개가 되면 return이 되며 같은 depth에 있던 배열끼리 크기를 비교하며 병합해나가 최종적으로 전체 배열을 정렬 하는 식으로 구성된다,

def merge_sort(a) -> None:

    def _merge_sort(a, left: int, right: int) -> None:

        #  left >= right가 되면 원소가 배열의 1개이다.
        if left < right:
            center = (left + right) // 2

             # 원소가 1개가 될때까지 재귀적으로 호출해준다.
            _merge_sort(a, left, center)
            _merge_sort(a, center + 1, right)

             # 배열의 인덱스를 다루기 위한 변수를 4개 선언한다.
            j = p = 0
            i = k = left


    ''' 
    임시 배열 buff에 a 원소를 center번째 까지 복사하고
    i는 a의 나머지에 접근하기 위해 (center 이후부터)
    p는 buff의 크기를 알기 위해사용된다.
    '''
            while i <= center:
                buff[p] = a[i]
                p += 1
                i += 1

        
    '''
    i가 a의 끝인 right에 도달하거나, 
    j가 buff크기(j == p)가 되기 전까지 
    크기를 비교하며 a[0]번째 부터 채워 나간다 (병합)
    '''
            while i <= right and j < p:
                if buff[j] <= a[i]:
                    a[k] = buff[j]
                    j += 1
                else:
                    a[k] = a[i]
                    i += 1
                k += 1


    '''
    전 단계의 반복문이 끝나고 j < p를 만족한다면 
    buff에 남은 배열들 모두가 a의 k번째까지의 원소들보다 모두 크다는 뜻이다.
    buff는 이미 재귀적 호출에서 정렬이 완료된 원소들이므로
    그대로 a에 복사해주면 된다.
    '''
            while j < p:
                a[k] = buff[j]
                k += 1
                j += 1

    n = len(a)
    buff = [None] * n
    _merge_sort(a, 0, n -1)
     # 메모리를 할당을 해제 해준다.
    del buff
    return a


print(merge_sort([3,4,1,8,9,33,21]))
>> [1, 3, 4, 8, 9, 21, 33]

병합정렬 특징

  • 병합정렬은 상한, 하한, 평균 모두 nlog(n)의 시간복잡도를 기대할 수 있는 알고리즘이다.
  • 같은 수끼리는 순서가 바뀌지 않는 안정 정렬이다.

Leave a comment