归并排序的原理:
每次对区间中的数据进行均分,将左半部分归并排序好,再将右半部分归并排序好,将左右两部分归并成一个有序序列
本质:先逐渐对区间进行均分,均分到区间中只有1个元素时然后再向上进行归并
归并:将两个有序区间合并成一个有序区间------给两个有序数组,将两个有序的数组合并成一个 有序数组
归并排序与快速排序类似的地方是:都需要对区间进行划分
不同地方:快速排序需要按照基准值对区间进行划分,存在极端情况,归并排序:每次都是对数据进行均分的不存在最差的情况
归并的图解
归并:
// 合并左右有序区间
// 时间复杂度:O(N)
void MergeData(int array[], int left, int mid, int right, int temp[])
{
int index1 = left, index2 = mid, index = left;
while (index1 < mid && index2 < right)
{
if (array[index1] <= array[index2])
temp[index++] = array[index1++];
else
temp[index++] = array[index2++];
}
// [left, mid)区间中的数据还没有搬移完
while (index1 < mid)
{
temp[index++] = array[index1++];
}
// [mid, right)区间中的数据还没有搬移完
while (index2 < right)
{
temp[index++] = array[index2++];
}
}
归并排序框架和后序遍历很像
快排和前序遍历像
void _MergeSort(int array[], int left, int right, int temp[])
{
// 如果区间有多个元素,先来找它的中间位置
if (right - left > 1)
{
int mid = left + ((right - left) >> 1);
// [left, mid) ,递归排左侧
_MergeSort(array, left, mid, temp);
// [mid, right),递归排右侧
_MergeSort(array, mid, right, temp);
// 将[left, mid)和[mid, right)有序区间进行归并
MergeData(array, left, mid, right, temp);
// 归并好之后,有序的数据在temp,将temp中有序的结果拷贝到原数组中
memcpy(array + left, temp + left, (right - left)*sizeof(array[left]));
}
}
// 归并排序
void MergeSort(int array[], int size)
{
int* temp = (int*)malloc(size*sizeof(array[0]));
if (NULL == temp)
return;
_MergeSort(array, 0, size, temp);
free(temp);
}