파게로그

[정렬] merge sort 본문

콤퓨타 왕왕기초/PS

[정렬] merge sort

파게 2020. 11. 8. 16:49

divide&conquer 방식의 알고리즘으로서 일반적으로 재귀 호출을 통해서 구현된다.

과정은 다음과 같다.

 

1. 리스트의 길이가 1 이하이면 이미 정렬된 리스트이다.

2. 정렬되지 않은 리스트를 동일한 또는 비슷한 크기의 두 개의 부분 리스트로 분할한다. (divide)

3. 각 부분 리스트를 재귀적으로 merge sort를 이용하여 정렬한다. (conquer)

4. 두 부분 리스트를 하나의 리스트로 병합한다. (combine)

 

[5, 2, 4, 7, 6, 1, 3, 8]

[5, 2, 4, 7] / [6, 1, 3, 8]

[5, 2] / [4, 7] // [6, 1] / [3, 8]

[5] / [2] // [4] / [7] /// [6] / [1] // [3] / [8] ↑divide ↓conquer, combine

[5, 2] / [4, 7] // [1, 6] / [3, 8]

[2, 4, 5, 7] / [1, 3, 6, 8]

[1, 2, 3, 4, 5, 6, 7, 8]

 

여기서 merge의 과정은 A=[2, 4, 7, 9]과 B=[1, 3, 5, 6]을 예로 들어 살펴보자.

i는 리스트 A에 대한 인덱스이고, j는 리스트 B에 대한 인덱스이다.

 

1. i=0, j=0 / A[0]과 B[0]을 비교하여 보다 작은 B[0]을 배열에 삽입.

A = [2, 4, 7, 9]

B = [1, 3, 5, 6]

 

2. i=0, j=1 / A[0]과 B[1]을 비교하여 보다 작은 A[0]을 배열에 삽입.

A = [2, 4, 7, 9]

B = [1, 3, 5, 6]

 

3. i=1, j=1 / A[1]과 B[1]을 비교하여 보다 작은 B[1]을 배열에 삽입.

A = [2, 4, 7, 9]

B = [1, 3, 5, 6]

 

4. i=1, j=2 / A[1]과 B[2]를 비교하여 보다 작은 A[1]을 배열에 삽입.

A = [2, 4, 8, 9]

B = [1, 3, 5, 6]

 

5. i=2, j=2 / A[2]와 B[2]를 비교하여 보다 작은 B[2]를 배열에 삽입.

 

6. i=2, j=3 / A[2]와 B[3]를 비교하여 보다 작은 B[3]을 배열에 삽입.

 

7. i=2, j=4 / B에 더 이상 비교할 원소가 없고, 이 때 A는 이미 정렬되어 있는 상태이므로 A[i]부터 차례대로 배열에 삽입.

A[3] 삽입.

 

시간복잡도

반드시 i, j 중 하나 이상은 1 이상씩 증가하면서 merge가 이루어지기에 정렬에 n만큼 소요되고,

리스트를 c개씩 분할했을 때, 이러한 과정이 log_c(n)만큼 발생하므로 O(nlog(n))이다.

 

특징

연결리스트로 구현함으로써 in-place-sort가 가능하다.

원래 리스트에서 앞에 있던 원소는 순서가 있는 다른 분할된 배열에 있거나,

또는 같은 부분 배열 안에 있더라도 위치가 바뀌지 않으므로 stable sort이다.

 

def merge(left, right):
    res = []
    i, j = 0, 0
    while(i<len(left) and j<len(right)):
        if left[i]<right[j]:
            res.append(left[i])
            i += 1
        else:
            res.append(right[j])
            j += 1
    while(i<len(left)):
        res.append(left[i])
        i += 1
    while(j<len(right)):
        res.append(right[j])
        j += 1

    return res

def merge_sort(arr):
    ### 리스트의 길이가 1 이하일 때, 이미 정렬이 완료된 것이다.
    if len(arr) <= 1: return arr

	### left, right로 분할한 후,
    ### 각각에 대해 merge sort을 시행하고,
    ### 그 후 merge한다.
    mid = len(arr) // 2
	
    left_arr = arr[:mid]
    right_arr = arr[mid:]
    left_arr = merge_sort(left_arr)
    right_arr = merge_sort(right_arr)

    return merge(left_arr, right_arr)



arr = [7, 2, 10, 21, 13, 14, 5, 18, 35, 9, 1, 2]
print(merge_sort(arr)) # [1, 2, 2, 5, 7, 9, 10, 13, 14, 18, 21, 35]

 

 

'콤퓨타 왕왕기초 > PS' 카테고리의 다른 글

[정렬] quick sort  (0) 2020.11.09
[정렬] insertion sort  (0) 2020.11.09
[정렬] bubble sort  (0) 2020.11.08
[정렬] heap sort  (0) 2020.11.06
[백준 1436번] 영화감독 숌  (0) 2020.11.06
Comments