分而治之
将两个有序数组合并成一个有序数组,时间复杂度是 O ( N ) O(N) O(N)。
void MergeArray(int len1,int len2,int*arr1,int* arr2,int* c)
{
int index1 = 0, index2 = 0;
int index3 = 0;
while (index1 < len1&&index2 < len2)
{ //取两数组中小的那个来排在数组c里
if(arr1[index1] <= arr2[index2])
c[index3++] = arr1[index1++];
else
c[index3++] = arr2[index2++];
}
while (index1 < len1)//arr1未排完,arr2排完了
//确保arr1排完,
c[index3++] = arr1[index1++];
while (index2 < len2)//arr2未排完,arr1排完了
//确保arr2排完
c[index3++] = arr2[index2++];
}
基于这样”分而治之“思想,假定给定一段序列要求排序,那么可以划分成子问题,将整段序列划分成左右两段,只要左右两段分别有序,那么该序列就有序,然后依次划分,直到划分为单个数据作为一组,一个数据肯定是有序的。
void MergeArray(int*arr, int*tmp, int left,int right)
{
if (left >= right)
return;
else
{
int index = 0;
int mid = (left + right) / 2;
MergeArray(arr, tmp, left, mid);
MergeArray(arr, tmp, mid + 1, right);//分治
//归并
int index1 = left, index2 = mid+1;
while (index1 <= left && index2 <= right)
{
if (arr[index1] < arr[index2])
tmp[index++] = arr[index1++];
else
tmp[index++] = arr[index2++];
}
while (index1 <= mid)
tmp[index++] = arr[index1++];
while (index2 <= right)
tmp[index++] = arr[index2++];
for (int i = 0; i < index; ++i)
arr[left+i] = tmp[i];
}
}
void MergeSort(int*arr,int n)
{
int*tmp = (int*)malloc(n*sizeof(int));
MergeArray(arr, tmp, 0, n - 1);
free(tmp);
}
优化:
由于是递归程序,随着递归深度的增减,对栈帧的消耗很大,尤其是归并的递归和快排类似,到了后面的划分,每组的数据量已经很小了,所以可以采用直接插入方式。
算法分析:
归并排序的时间复杂度为
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)。空间复杂度:
O
(
n
)
O(n)
O(n),归并是稳定排序。
若从空间复杂度来考虑:首选堆排序,其次是快速排序,最后是归并排序。