[数据结构]归并排序

算法思想

  归并排序与前面介绍过的基于交换、选择等排序的思想不一样,“归并”的含义是将两个或两个以上的有序表组合成一个新的有序表。假定待排序表含有n个记录,则可以看成是n个有序的子表,每个子表长度为1,然后两两归并,得到[n/2]个长度为2或1的有序表;再两两归并,……如此重复,直到合并成一个长度为n的有序表为止,这种排序方法称为2-路归并排序。下面给出一个2路归并排序的一个例子:
  这里写图片描述
  Merge()的功能是将前后相邻的两个有序表归并为一个有序表的算法。设两段有序表A[low…mid]、A[mid+1…high]存放在同一个顺序表中相邻的位置上,先将它们复制到辅助数组B中。每次从对应B中的两个段取出一个记录进行关键字的比较,将较小者放入A中,当数组B中有一段的下标超出其对应的表长时(即该段的所有元素已经完全复制到A中),将另一段中剩余部分直接复制到A中,下面给出其算法:

算法代码

Elemtype *B=[Elemtype*]malloc((n+1)*sizeof(Elemtype));//辅助数组B
void Merge(Elemtype A[],int low,int mid,int high){
//表A的两段A[low...mid]和A[mid+1...high]各自有序,将它们合并成一个有序表
    for(int k=low;k<=high;k++)
        B[k]=A[k];//将A中所有元素复制到B中
    for(i=low,j=mid+1,k=i;i<=mid&&j<=high;k++){
        if(B[i]<=B[j])//比较B的两段中的元素
            A[k]=B[i++];//将较小值复制到A中
        else
            A[k]=B[j++];
    }
    while(i<=mid) A[k++]=B[j++];//若第一个表没有检测完,复制
    while(j<=high) A[k++]=B[j++];//若第二个表没有检测完,复制
}

  一趟归并排序的操作是,调用[n/2h]次算法merge()将L[1…n]中前后相邻且长度为h的有序段进行两两归并,得到前后相邻、长度为2h的有序段,整个归并排序需要进行[log₂n]趟。
  递归形式的2-路归并排序算法是基于分治的,其过程如下:
  分解:将含有n个元素的待排序表分成各含n/2个元素的子表,采用2-路归并排序算法对两个子表递归地进行排序。
  合并:合并两个已排序的子表得到排序结果。
  

void MergeSort(Elemtype 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);//归并
    }
}

算法性能

  空间复杂度:Merge()操作中,辅助空间刚好要占用n个单元,所有归并排序的空间复杂度为O(n)。
  时间复杂度:每一趟归并的时间复杂度为O(n),共需要进行log₂n趟归并,所以算法的时间复杂度为O(nlog₂n)。
  稳定性:由于Merge()操作不会改变相同关键字的相对次序,所以2-路归并排序算法是一个稳定的排序算法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值