归并排序算法利用合并的思想,先将序列拆分为两部分分别排序,再将两个有序序列合并为一个有序序列从而达到排序的目的。它的时间复杂度为O(nlgn),空间复杂度为O(n)。
归并排序的思想对于要比较序列中任意两个元素的问题提供了一个比O(n^2)快速的解决方案。比如求序列的逆序数(http://blog.csdn.net/iuyo89007/article/details/17208949),求序列中满足和为X(或其他要求)的数有几对(http://blog.csdn.net/iuyo89007/article/details/17455177)等,另外,归并排序还可以用在外部排序上,可以先把数据分解为多个小文件,然后每个小文件分别排序(可用其他排序算法),再利用归并排序的合并过程把这些小文件合并成一个有序的大文件,从而完成外部排序。
下面是归并排序的递归和非递归实现。
//归并排序
void merge(int *A, int low, int mid, int high)
{
int *merge = new int[high-low+1]; //申请合并空间
if (!merge)
{
return;
}
int i = low, j = mid+1, k = 0;
while (i<=mid && j<=high)
{
if (A[i] <= A[j])
merge[k++] = A[i++];
else
merge[k++] = A[j++];
}
while(i<=mid)
merge[k++] = A[i++];
while(j<=high)
merge[k++] = A[j++];
k=0;
while(low<=high)
{
A[low++] = merge[k++];
}
delete []merge;
}
//归并排序递归版
void mergeSort(int *A, int low, int high)
{
if (low<high)//绝对不能有等号
{
int mid = (low+high)/2;
mergeSort(A, low, mid);
mergeSort(A, mid+1, high);
merge(A, low, mid, high);
}
}
//归并排序非递归版
void mergeSort(int *A, int n)
{
int mid, high;
for (int k=2; k/2<n; k*=2) //k为合并规模
{
for (int low=0; low<n; low+=k) //每个规模的low
{
high = low+k-1;
if (high>n-1) //n不是2的n次方,high最终会越界
high = n-1;
if (k-1>n)//说明是最后一次合并
mid = (k-1)/2;
else
mid = (low+high)/2;
if (low < high)
{
merge(A, low, mid, high);
}
}
}
}