一、算法思想
归并排序可以看作一个分而治之的过程:先将整个序列分为两半,对每一半分别进行归并排序,将得到两个有序序列,然后将这两个序列归并成一个序列即可
二、算法过程
三、实现
// SR和TR1、TR2是等长的,由于是对不同的区间进行修改,故各子过程不会相互影响
// SR不会发生改变
// TR2存储的是中间过程
// TR1的结果会返回到上一层的TR2,作为上一层的中间结果
void mergeSort(int SR[],int TR1[],int low,int high)
// 将无序的SR[low...high]归并排序为有序的TR1[low...high]
{
if(low==high) TR1[low]=SR1[low];
else
{
int mid=(low+high)/2;
mergeSort(SR,TR2,low,mid); // 归并排序前半段,将无序的SR[low...mid]归并排序为有序的TR2[low...mid]
mergeSort(SR,TR2,mid+1,high); // 归并排序后半段,将无序的SR[mid+1...high]归并排序为有序的TR2[mid+1...high]
merge(TR2,TR1,low,mid,high); // 将TR2[low...mid]和TR2[mid+1...high]归并到TR1[low...high]
}
}
void merge(int TR2[],int TR1[],int low,int mid,int high)
// 将有序TR2[low...mid]和TR2[mid+1...high]归并到TR1[low...high]
{
int i=low; // i指示TR2[low...mid]的首位,j指示TR2[mid+1...high]的首位,
// k指示TR1[low...high]的首位
int j=mid+1;
for(k=i;i<=mid&&j<=high;k++)
{
if(TR2[i]<=TR2[j])
{
TR1[k]=TR2[i];
i++;
}
else
{
TR1[k]=TR2[j];
j++;
}
}
while(i<=mid)
{
TR1[k]=TR2[i];
i++;
k++;
}
while(j<=high)
{
TR1[k]=TR2[j];
j++;
k++;
}
}
四、算法性能分析
(1)时间复杂度分析
由算法程序可得 T(n)=T(n/2)+n,其中,n是指当前的 归并操作 的执行次数(即:要归并的两个子序列中关键字个数之和),故时间复杂度为 O(nlog n)
可见归并排序时间复杂度和初始序列无关,即平均时间复杂度、最好时间复杂度、最坏时间复杂度均为 O(nlog n)
(2)空间复杂度分析
因为归并排序需要转存整个待排序列,需要用到TR1[ ]和TR2[ ],故其空间复杂度为O(n)
(3)稳定性
归并排序是把序列递归地分成短序列,递归出口是短序列只有1个元素(认为直接有序)或者2个序列(1次比较和交换),然后把各个有序的段序列合并成一个有序的长序列,不断合并直到原序列全部排好序。可以发现,在1个或2个元素时,1个元素不会交换,2个元素如果大小相等也没有人故意交换,这不会破坏稳定性。那么,在短的有序序列合并的过程中,稳定是是否受到破坏?没有,合并过程中我们可以保证如果两个当前元素相等时,我们把处在前面的序列的元素保存在结果序列的前面,这样就保证了稳定性。所以,归并排序也是稳定的排序算法。