자료구조
자료구조 - 합병 정렬
tita
2024. 6. 11. 13:52
[합병 정렬(Merge Sort)]
합병 정렬(Merge Sort)은 분할 정복 알고리즘의 하나로, 리스트를 반으로 나누어 각각을 정렬한 다음, 합병하여 전체 리스트를 정렬하는 방법입니다.
재귀적인 구조를 가지며, 리스트의 길이가 1이 될 때까지 계속하여 반으로 나누고, 나중에 합병하면서 정렬합니다. 합병 정렬은 안정적인 정렬 알고리즘이며, 시간 복잡도는 항상 입니다.
합병 정렬 과정
- 리스트를 반으로 나눕니다.
- 각 부분 리스트를 재귀적으로 합병 정렬을 호출하여 정렬합니다.
- 정렬된 부분 리스트를 합병하여 전체 리스트를 정렬합니다.
합병 정렬 의사 코드
함수 mergeSort(arr):
if 리스트의 길이(arr) <= 1:
반환 arr
// 리스트를 반으로 나눔
mid = 리스트의 길이(arr) / 2
left_half = arr의 처음부터 mid까지의 부분 리스트
right_half = arr의 mid부터 끝까지의 부분 리스트
// 각 부분 리스트를 재귀적으로 정렬
left_half = mergeSort(left_half)
right_half = mergeSort(right_half)
// 정렬된 부분 리스트를 합병하여 정렬
반환 merge(left_half, right_half)
함수 merge(left, right):
result = 빈 배열
while left와 right가 비어있지 않은 동안:
if left의 첫 번째 요소 <= right의 첫 번째 요소:
result에 left의 첫 번째 요소를 추가하고 left에서 삭제
else:
result에 right의 첫 번째 요소를 추가하고 right에서 삭제
// 남은 요소들을 추가
result += left
result += right
반환 result
합병 정렬 예제
예시 리스트: [64, 25, 12, 22, 11]
첫 번째 재귀 호출:
리스트를 반으로 나누어 각각 [64, 25], [12, 22, 11]로 분할합니다.
각 부분 리스트를 재귀적으로 정렬합니다.
두 번째 재귀 호출:
[64, 25]를 정렬하여 [25, 64]로 반환합니다.
[12, 22, 11]를 정렬하여 [11, 12, 22]로 반환합니다.
합병 과정:
[25, 64]와 [11, 12, 22]를 합병하여 정렬합니다.
결과: [11, 12, 22, 25, 64]
합병 정렬 코드
#include <iostream>
#include <vector>
using namespace std;
// 두 개의 정렬된 부분 리스트를 합병하여 정렬된 리스트를 반환
vector<int> merge(vector<int>& left, vector<int>& right)
{
vector<int> result;
int left_index = 0, right_index = 0;
// left와 right가 비어있지 않은 동안 반복
while (left_index < left.size() && right_index < right.size())
{
if (left[left_index] <= right[right_index])
{
result.push_back(left[left_index]);
left_index++;
}
else
{
result.push_back(right[right_index]);
right_index++;
}
}
// 남은 요소들을 추가
while (left_index < left.size())
{
result.push_back(left[left_index]);
left_index++;
}
while (right_index < right.size())
{
result.push_back(right[right_index]);
right_index++;
}
return result;
}
// 합병 정렬 함수
vector<int> mergeSort(vector<int>& arr)
{
int n = arr.size();
// 리스트의 길이가 1 이하이면 그대로 반환
if (n <= 1)
{
return arr;
}
// 리스트를 반으로 나눔
int mid = n / 2;
vector<int> left_half(arr.begin(), arr.begin() + mid);
vector<int> right_half(arr.begin() + mid, arr.end());
// 각 부분 리스트를 재귀적으로 정렬
left_half = mergeSort(left_half);
right_half = mergeSort(right_half);
// 정렬된 부분 리스트를 합병하여 반환
return merge(left_half, right_half);
}
int main()
{
vector<int> arr = {64, 25, 12, 22, 11}; // 예제 리스트
cout << "정렬 전: ";
for (int i : arr)
{
cout << i << " ";
}
cout << endl;
arr = mergeSort(arr); // 합병 정렬 수행
cout << "정렬 후: ";
for (int i : arr)
{
cout << i << " ";
}
cout << endl;
return 0;
}