【概述】
归并排序是一种稳定的排序方法,其是分治策略的一个非常典型的应用。
其基本思想是:将 n 个待排序的记录看成是 n 个长度为 1 的有序序列,然后两两进行归并,第一轮得到 [n/2] 个长度为 2 的有序序列,第二轮得到 [n/4] 个长度为 4 的有序序列,以此类推,直到得到一个长度为 n 的有序序列。
【排序过程】
归并排序的核心是归并操作,即将两个已经排序的序列合并成一个序列的操作,其步骤如下:
- 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
- 设定两个指针,最初位置分别为两个已经排序序列的起始位置
- 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
- 重复步骤 3 直到某一指针到达序列尾
- 将另一序列剩下的所有元素直接复制到合并序列尾
在实际排序过程中,通过对归并操作的递归调用,即可完成归并排序。
排序过程 宏观过程
【时空复杂度分析】
一趟归并排序需要将待排序序列扫描一遍,其时间复杂度为 O(n),而整个归并排序需要进行 趟,因此,总的时间复杂度为 O(nlogn)
由于待排序序列并不影响归并排序的过程,因此无论是最好、最坏时间复杂度,还是平均时间复杂度,均为 O(nlogn)
此外,归并排序再归并过程中,需要与待排序记录序列同样数量的存储空间,以便存放归并结果,因此其空间复杂度为 O(n)
【源程序】
void mergeArray(int a[],int left,int mid,int right,int temp[]){
int i=left,j=mid+1;
int k=0;
while(i<=mid&&j<=right){
if(a[i]<=a[j])//取a[i]与a[j]中的小者放入temp[k]
temp[k++]=a[i++];
else
temp[k++]=a[j++];
}
while(i<=mid)//第一个子序列未处理完
temp[k++]=a[i++];
while(j<=right)//第二个子序列未处理完
temp[k++]=a[j++];
for(int i=0;i<k;i++)//将数组temp中的值返回数组a
a[left+i]=temp[i];
}
void mergeSort(int a[],int left,int right,int temp[]){
if(left<right){
int mid=(left+right)/2;
mergeSort(a,left,mid,temp);//左边有序
mergeSort(a,mid+1,right,temp);//右边有序
mergeArray(a,left,mid,right,temp);//将二个有序数列合并
}
}