-
[알고리즘] 병합 정렬 (Merge Sort)Study/자료구조,알고리즘 2022. 11. 4. 18:21
01. 병합 정렬의 개념
- 안정 정렬이다.
- 정렬을 위한 별도의 공간이 필요하다.
- 분할 정복 알고리즘이다.
- 주로 순환 호출로 구현
- 매우 빠른 속도를 보장 ( O(NlogN) )
02. 과정 설명
- 배열을 반으로 나누는 것을 반복한다.
- 사이즈 1짜리 배열까지 나누고 나면, 나눈 순서의 역순으로 정렬해가며 부분 배열을 합친다.
말로는 사실 설명할 게 별로 없다...
그림으로 보는 게 더 설명이 쉬울 듯 하여 첨부
03. C++ 코드
void Merge(int*& arr, int*& tmp, int left, int right) { if (left == right) return; int l = left; int mid = (l + right) / 2; int midIdx = mid + 1; int idx = l; // 작은 원소 순서대로 임시 배열에 채워넣는다. while (l <= mid && midIdx <= right) { if (arr[l] < arr[midIdx]) tmp[idx++] = arr[l++]; else tmp[idx++] = arr[midIdx++]; } // 남아있는 원소들을 임시 배열에 넣는다. while (l <= mid) tmp[idx++] = arr[l++]; while (midIdx <= right) tmp[idx++] = arr[midIdx++]; // 원래 배열에 정렬된 임시 배열을 복사 for (int i = left; i <= right; ++i) arr[i] = tmp[i]; } void MergePartitioning(int*& arr, int*& tmp, int left, int right) { if (left >= right) return; int mid = (left + right) / 2; // 분할부터 수행한다 MergePartitioning(arr, tmp, left, mid); MergePartitioning(arr, tmp, mid + 1, right); // 부분 배열을 합병 정렬한다. Merge(arr, tmp, left, right); } void MergeSort() { cout << "Merge Sort : " << endl; int* arr = new int[6]{ 5, 1, 8, 9, 7, 3 }; int* tmp = new int[6]{ 0, 0, 0, 0, 0, 0 }; MergePartitioning(arr, tmp, 0, 5); for (int i = 0; i < 6; ++i) cout << arr[i] << " "; cout << '\n'; delete[] arr; delete[] tmp; }
05. 병합 정렬의 시간 복잡도
- 레코드의 크기 N = 2^k 인 경우, 순환 호출의 깊이는 pivot에 의해 균등하게 나누어진다고 가정할 때 log2^k = k이다.
- size 1 짜리 부분 배열은 비교를 위해 1번의 연산을 수행
- size 2 짜리 부분 배열은 비교를 위해 2번의 연산을 수행
- size 4 짜리 부분 배열은 비교를 위해 4번의 연산을 수행
- 2^k-1 짜리 부분 배열은 비교를 2^k-1 번 하게 되고, 이 부분 배열은 2개가 있다.
- 따라서 비교 연산은 2^k-1 * 2 = 2^k 번
- 즉, 각 순환 호출마다 N번의 연산을 수행하게 된다.
- 따라서 전체 시간 복잡도는 O(NlogN)
'Study > 자료구조,알고리즘' 카테고리의 다른 글
[자료구조] C++ HashTable 구현 (0) 2022.11.11 꼬리 재귀 (Tail Recursion) (0) 2022.11.03 [알고리즘] 퀵 정렬 (Quick Sort) (0) 2022.11.03 [알고리즘] 카운팅 정렬(Counting Sort) (0) 2022.10.21 [알고리즘] Bubble Sort와 Selection Sort 시간 비교 (0) 2022.10.20