병합 정렬 (Merge Sort) (C++)
2025. 1. 4. 22:35ㆍ소프트웨어/알고리즘
병합 정렬 (Merge Sort)
병합 정렬은 분할 정복(Divide and Conquer) 알고리즘을 사용하는 정렬 기법으로, 배열을 재귀적으로 두 부분으로 나누고, 각각을 정렬한 뒤 병합(Merge)하여 정렬된 배열을 만드는 방식. 안정적이며, 정렬 성능이 O(nlogn)으로 일정한 점에서 효율적.
동작 원리
- 분할 (Divide):
- 배열을 두 개의 하위 배열로 분할.
- 하위 배열의 크기가 1이 될 때까지 재귀적으로 반복.
- 정복 (Conquer):
- 두 개의 정렬된 하위 배열을 병합하여 하나의 정렬된 배열로 만든다.
- 병합 (Merge):
- 병합 과정에서 두 배열을 비교하며 작은 값을 먼저 결과 배열에 추가.
특징
- 시간 복잡도:
- 최선/평균/최악: O(nlogn) (데이터 분할 O(logn), 병합 )
- 공간 복잡도: O(n) (추가 메모리 필요)
- 안정적 정렬: 동일한 값의 순서가 유지.
- 효율성: 데이터 크기와 상관없이 일정한 성능.
예제 코드 (C++)
오름차순 병합 정렬
#include <iostream>
#include <vector>
using namespace std;
// 병합 함수: 두 정렬된 배열을 병합하여 하나의 정렬된 배열로 만듦
void merge(vector<int>& arr, int left, int mid, int right) {
vector<int> temp; // 임시 배열
int i = left; // 왼쪽 배열의 시작
int j = mid + 1; // 오른쪽 배열의 시작
// 두 배열을 비교하여 작은 값을 temp에 추가
while (i <= mid && j <= right) {
if (arr[i] <= arr[j]) {
temp.push_back(arr[i++]);
} else {
temp.push_back(arr[j++]);
}
}
// 왼쪽 배열의 남은 요소 추가
while (i <= mid) {
temp.push_back(arr[i++]);
}
// 오른쪽 배열의 남은 요소 추가
while (j <= right) {
temp.push_back(arr[j++]);
}
// 정렬된 값을 원래 배열에 복사
for (int k = left; k <= right; ++k) {
arr[k] = temp[k - left];
}
}
// 병합 정렬 함수: 배열을 재귀적으로 분할하고 병합
void mergeSort(vector<int>& arr, int left, int right) {
if (left < right) {
int mid = left + (right - left) / 2; // 중간 인덱스
mergeSort(arr, left, mid); // 왼쪽 부분 정렬
mergeSort(arr, mid + 1, right); // 오른쪽 부분 정렬
merge(arr, left, mid, right); // 두 부분 병합
}
}
int main() {
vector<int> arr = {12, 11, 13, 5, 6, 7};
cout << "정렬 전 배열: ";
for (int num : arr) cout << num << " ";
cout << endl;
mergeSort(arr, 0, arr.size() - 1);
cout << "정렬 후 배열: ";
for (int num : arr) cout << num << " ";
cout << endl;
return 0;
}
코드 설명
- merge 함수:
- 두 개의 정렬된 하위 배열을 병합.
- 작은 값을 먼저 추가하면서 정렬된 결과를 생성.
- mergeSort 함수:
- 배열을 재귀적으로 분할.
- 각 부분을 병합하여 정렬된 배열로 만든다.
- 재귀 종료 조건:
- 배열의 크기가 1 이하일 경우(즉, left >= right) 재귀 호출을 종료.
예제 동작 과정
입력 배열: [12, 11, 13, 5, 6, 7]
- 분할 과정:
- [12, 11, 13, 5, 6, 7] → [12, 11, 13] & [5, 6, 7]
- [12, 11, 13] → [12] & [11, 13] → [11] & [13]
- [5, 6, 7] → [5] & [6, 7] → [6] & [7]
- 병합 과정:
- [11] & [13] → [11, 13]
- [12] & [11, 13] → [11, 12, 13]
- [6] & [7] → [6, 7]
- [5] & [6, 7] → [5, 6, 7]
- [11, 12, 13] & [5, 6, 7] → [5, 6, 7, 11, 12, 13]
- 최종 정렬된 배열: [5, 6, 7, 11, 12, 13]
장점과 단점
장점
- 항상 O(nlogn)의 시간 복잡도를 보장.
- 안정적 정렬: 데이터의 상대적 순서가 유지됨.
- 대규모 데이터에서 일정한 성능.
단점
- 추가 메모리가 필요 ().
- 작은 데이터 크기에서는 다른 정렬(삽입 정렬 등)보다 느림.
활용 사례
- 대규모 데이터 정렬에 적합.
- 안정적 정렬이 필요한 경우(예: 데이터베이스 시스템).
'소프트웨어 > 알고리즘' 카테고리의 다른 글
그래프 이론 - 1. 그래프 이론 기초 (0) | 2025.02.21 |
---|---|
힙 정렬 (Heap Sort) (C++) (0) | 2025.01.04 |
퀵 정렬 (Quick Sort) (C++) (0) | 2025.01.04 |
삽입 정렬 (Insertion Sort) (C++) (0) | 2025.01.04 |
선택 정렬 (Selection Sort) (C++) (0) | 2025.01.04 |