ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 병합(합병) 정렬(Merge Sort)
    알고리즘/분할정복 2024. 8. 4. 20:18

     병합정렬(Merge-sort)은 퀵 정렬(Quick Sort)와 같이 분할정복 알고리즘을 이용한 정렬 알고리즘중 하나입니다. 선택정렬같은 O(N²)의 느린 정렬 알고리즘과 다르게 병합정렬은 시간복잡도 O(NlogN)의 빠른 정렬 알고리즘입니다.


    「병합 정렬의 동작 과정」


    1. 분할 과정 (Divide)

     병합정렬의 첫 번째 단계인 분할과정에서는 배열을 가능한 한 작게 나눕니다. 이 단계에서는 배열을 중간을 기준으로 두 개의 하위 배열로 분할합니다. 이 과정을 배열에 원소가 하나가 될때까지 계속 반복하면 됩니다.

     

    -처음 주어진 배열 ↓

    [38, 27, 43, 3, 9, 82, 10]

    -첫번째 분할 ↓

    [38, 27, 43], [3, 9, 82, 10]

    -두번째 분할 

    [38, 27], [43],  [3, 9], [82, 10]

    -세번째 분할

    [38], [27], [3], [9], [82], [10]


    2. 정복 과정 (Conquer)

     정복(Conquer) 단계에서는 위 과정에서 나누어진 배열들중 서로 인접한 배열을 비교하며 병합합니다. 배열의 크기가 1이 될 때까지 분할한 배열들을 두 개씩 비교하여 정렬된 배열로 병합합니다. 이 과정을 반복하여 더 큰 정렬된 배열을 만듭니다.

    -첫번째 과정

    [38]과 [27]을 비교하여 [27, 38]으로 병합

    -두번째 과정

    [3]과 [9]을 비교하여 [3, 9]으로 병합

    -세번째 과정

    [82]과 [10]을 비교하여 [10, 82]으로 병합


    3. 결합 과정 (Combine)

     마지막 결합 단계는 정렬된 하위 배열들을 다시 병합하여 최종적으로 전체 배열을 정렬된 상태로 만드는 과정입니다.

    -첫번째 과정

    [27, 38]과 [43]을 병합하여 [27, 38, 43]으로 병합

    -두번째 과정

    [3, 9]과 [10, 82]을 병합하여 [3, 9, 10, 82]으로 병합

    -마지막 과정

    [27, 38, 43]과 [3, 9, 10, 82]을 병합하여 최종 정렬된 배열 [3, 9, 10, 27, 38, 43, 82]이 만들어짐.

    하지만 이렇게만 보면 결합과정에 대해 이해가 안가기 때문에 마지막 과정을 통해 결합과정(Combine 또는 Merge)에 대해 자세히 설명해보겠습니다.

     

    배열 a

    27 38 43

    배열 b

    3 9 10 82

     

    위 두 배열을 Merge하는 과정은 다음과 같습니다.

    27 38 43
    i    
    3 9 10 82
    j      

     

    i의 값과 j의 값을 비교하여 더 작은 값을 정답 배열에 넣어줍니다. 

     

    -현재 정답배열 = [3]

     

    넣었다면 더 작은 배열의 idx값인 j를 증가시킵니다.

    27 38 43
     i    
    3 9 10 82
       j    

     

    그후 i의 값과 j의 값을 비교하여 더 작은 값을 정답 배열에 넣어줍니다. 

     

    -현재 정답배열 = [3, 9]

     

    넣었다면 더 작은 배열의 idx값인 j를 증가시킵니다.

    27 38 43
     i    
    3 9 10 82
         j  

     

    그후 i의 값과 j의 값을 비교하여 더 작은 값을 정답 배열에 넣어줍니다. 

     

    -현재 정답배열 = [3, 9, 10]

     

    넣었다면 더 작은 배열의 idx값인 j를 증가시킵니다.

    27 38 43
     i    
    3 9 10 82
           j

     

    그후 i의 값과 j의 값을 비교하여 더 작은 값을 정답 배열에 넣어줍니다. 

     

    -현재 정답배열 = [3, 9, 10, 27]

     

    넣었다면 더 작은 배열의 idx값인 i를 증가시킵니다.

    27 38 43
       i  
    3 9 10 82
           j

     

    그후 i의 값과 j의 값을 비교하여 더 작은 값을 정답 배열에 넣어줍니다. 

     

    -현재 정답배열 = [3, 9, 10, 27, 38]

     

    넣었다면 더 작은 배열의 idx값인 i를 증가시킵니다.

    27 38 43
         i
    3 9 10 82
           j

     

    그후 i의 값과 j의 값을 비교하여 더 작은 값을 정답 배열에 넣어줍니다. 

     

    -현재 정답배열 = [3, 9, 10, 27, 38, 43]

     

    넣었다면 더 작은 배열의 idx값인 i를 증가시켜야 하지만 a배열은 이미 끝났음으로 남은 b배열을 모두 정답에 넣어줍니다.

     

    -현재 정답배열 = [3, 9, 10, 27, 38, 43, 82]

     

    이 과정을 모든 결합과정에서 해준다면 배열이 모두 정렬됩니다.


    병합정렬을 공부했으니 다음 문제를 병합정렬을 통해 풀어보자

    https://www.acmicpc.net/problem/2751

    《소스코드》

    더보기
    더보기
    더보기
    더보기
    #include <stdio.h>
    
    int n;
    int arr[1000010];
    int res[1000010];
    
    void Merge(int low, int mid, int high) {
    	int i;
    	
    	int res_len = 0;
    	int pointer_first = low;
    	int pointer_second = mid + 1;
    
    	while (pointer_first <= mid && pointer_second <= high) {
    		if (arr[pointer_first] < arr[pointer_second]) {
    			res[res_len++] = arr[pointer_first++];
    		}
    		else {
    			res[res_len++] = arr[pointer_second++];
    		}
    	}
    	if (pointer_first > mid) {
    		for (i = pointer_second; i <= high; i++) {
    			res[res_len++] = arr[i];
    		}
    	}
    	else if (pointer_second > high) {
    		for (i = pointer_first; i <= mid; i++) {
    			res[res_len++] = arr[i];
    		}
    	}
    	for (i = low; i <= high; i++) {
    		arr[i] = res[i - low];
    	}
    	return;
    }
    
    void Merge_sort(int low, int high) {
    	int mid = (low + high) / 2;
    	if (low >= high) return;
    	Merge_sort(low, mid);
    	Merge_sort(mid + 1, high);
    	Merge(low, mid, high);
    }
    
    int main()
    {
    	int i;
    	scanf("%d", &n);
    	for (i = 0; i < n; i++) scanf("%d", &arr[i]);
    	Merge_sort(0, n - 1);
    	for (i = 0; i < n; i++) printf("%d\n", arr[i]);
    	return 0;
    }

    '알고리즘 > 분할정복' 카테고리의 다른 글

    이진 탐색(Binary Search)  (0) 2024.08.06
    퀵 정렬(Quick Sort)  (0) 2024.08.06
    분할 정복(Divide and conquer) 알고리즘  (0) 2024.08.04
Designed by Tistory.