알고리즘/지식
[정렬 알고리즘] 합병 정렬
미니소곰
2020. 3. 3. 17:40
퀵정렬 처럼, 합병정렬은 분할 정복 알고리즘입니다.
주어진 배열을 두개로 나누고, 두개의 배열을 인자로 합병정렬 함수 호출을 합니다. 그리고 정렬된 두 배열을 병합합니다.
merge() 함수는 두개의 배열을 합병하는데 사용됩니다.
merge(arr, left, middle, right)은 arr[left ... middle]과 arr[middle+1 ... right]이 정렬되었다는 가정하에 두개의 서브배열을 합병합니다.
mergeSort(arr[], left, right) if( right > left) 1. 중간 지점을 찾아서 두개로 나눕니다. middle = (left+right)/2 2. 왼쪽 부분 배열로 mergeSort를 호출합니다. mergeSort(arr, left, middle) 3. 오른쪽 부분 배열로 mergeSort를 호출합니다. mergeSort(arr, middle+1, right) 4. 두개의 부분 배열을 합병합니다. merge(arr, left, middle, right) |
#include<stdlib.h>
#include<stdio.h>
#include<cstring>
#include<iostream>
using namespace std;
void printArray(int A[], int size);
//두개의 배열을 합병합니다.
//left~middle, middle+1~right 까지
void merge(int arr[], int left, int middle, int right)
{
int left_size = middle - left + 1;
int right_size = right - middle;
/* 임시 배열을 만듭니다. */
int Left[left_size], Right[right_size];
/* 왼쪽 오른쪽 배열에 값을 복사합니다. */
memcpy(Left, &arr[left], left_size*sizeof(int));
memcpy(Right, &arr[middle+1], right_size*sizeof(int));
/* Merge the temp arrays back into arr[l..r]*/
int i=0;
int j=0;
int k = left; // Initial index of merged subarray
// 둘다 합병이 끝나지 않은경우
while (i < left_size && j < right_size)
{
//작은 값을 먼저 넣는다.
if (Left[i] <= Right[j])
{
arr[k] = Left[i];
i++;
}
else
{
arr[k] = Right[j];
j++;
}
k++;
}
/* 왼쪽에 값이 남은경우 */
if(i < left_size)
{
memcpy(&arr[k], &Left[i], (left_size - i)*sizeof(Left[0]));
}
/* 오른쪽 배열에 값이 남은경우 */
if (j < right_size)
{ //인덱스 - 인덱스가 아닌 갯수에서 j를 빼는 거라 +1할 필요가 없다
memcpy(&arr[k], &Right[j], (right_size - j)*sizeof(Right[0]));
}
}
//정렬하려는 배열의 왼쪽, 오른쪽 인덱스를 넣어준다.
void mergeSort(int arr[], int left, int right)
{
if (left < right) //오른쪽 인덱스가 더 큰경우만 시행
{
//(left+right)/2랑 같으나 오버플로우를 막기
int middle = left+(right-left)/2;
//배열을 나누어 재귀함수 호출한다.
mergeSort(arr, left, middle);
mergeSort(arr, middle+1, right);
//나눈 배열들을 합병한다.
merge(arr, left, middle, right);
}
}
void printArray(int A[], int size)
{
int i;
for (i=0; i < size; i++)
cout<<A[i]<<" ";
cout<<endl;
}
int main()
{
int arr[] = {12, 11, 13, 5, 6, 7};
int arr_size = sizeof(arr)/sizeof(int);
cout<<"Given array is"<<endl;
printArray(arr, arr_size);
mergeSort(arr, 0, arr_size - 1);
cout<<endl<<"Sorted array is"<<endl;
printArray(arr, arr_size);
return 0;
}
시간복잡도
O(n log(n))
제자리 정렬이 아니며, 안정정렬이다
"주어진 배열을 최대한으로 나눈 뒤 합병하면서 정렬시키는 방식이다."