Loading

[数据结构]归并排序

算法思想

  归并排序与前面介绍过的基于交换、选择等排序的思想不一样,“归并”的含义是将两个或两个以上的有序表组合成一个新的有序表。假定待排序表含有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-路归并排序算法是一个稳定的排序算法。

posted @ 2017-04-30 17:31  李正浩  阅读(104)  评论(0编辑  收藏  举报