数据结构复习-归并排序和基数排序

1.归并排序

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

ElemType *B=(ElemType *)malloc((n+1)*sizeof(ElemType)); 
void Merge(ElemType A[],int low,int mid,int high) {
    for(int k=low; k<=high; k++) {
        B[k]=A[k];
    }
    for(i=low,j=mid+1,k=i;i<=mid&&j<=high;k++){
        if(B[i]<=B[j])
            A[k]=B[i++];
        else
            A[k]=B[j++];
    }
    while(i<=mid)
        A[k++]=B[i++];
    while(j<=high)
        A[k++]=B[j++];
}

一趟归并排序的操作是,调用到⌈n/2h⌉次算法merge()将L[1...n]中前后相邻且长度为h的有序段进行两两归并,得到前后相邻、长度为2h的有序段,整个归并排序需要进行到⌈log2(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);
    }
}

2-路归并排序算法的性能分析如下:
空间效率:Merge()操作中,辅助空间刚好占用n个单元,所以归并排序的空间复杂度为O(n)。
时间效率:每一趟归并的时间复杂度为O(n),共需要进行到⌈log2(n)⌉趟归并,所以算法的时间复杂度为O(nlog2(n))。
稳定性:由于Merge()操作不会改变相同关键字记录的相对次序,所以2-路归并排序算法是一个稳定的排序算法。

2.基数排序

基数排序是一种很特殊的排序方法,它不是基于比较进行排序的,而是采用多关键字排序思想(即基于关键字各位的大小进行排序的),借助“分配”和“收集”两种操作对单逻辑关键字进行排序。基数排序又分为最高位优先(MSD)排序和最低位优先(LSD)排序。

以LSD为例,假设原来有一串数值如下所示:
73, 22, 93, 43, 55, 14, 28, 65, 39, 81
首先根据个位数的数值,在走访数值时将它们分配至编号0到9的桶子中:
0
1 81
2 22
3 73 93 43
4 14
5 55 65
6
7
8 28
9 39
接下来将这些桶子中的数值重新串接起来,成为以下的数列:
81, 22, 73, 93, 43, 14, 55, 65, 28, 39
接着再进行一次分配,这次是根据十位数来分配:
0
1 14
2 22 28
3 39
4 43
5 55
6 65
7 73
8 81
9 93
接下来将这些桶子中的数值重新串接起来,成为以下的数列:
14, 22, 28, 39, 43, 55, 65, 73, 81, 93
这时候整个数列已经排序完毕;如果排序的对象有三位数以上,则持续进行以上的动作直至最高位数为止。
LSD的基数排序适用于位数小的数列,如果位数多的话,使用MSD的效率会比较好。MSD的方式与LSD相反,是由高位数为基底开始进行分配,但在分配之后并不马上合并回一个数组中,而是在每个“桶子”中建立“子桶”,将每个桶子中的数值按照下一数位的值分配到“子桶”中。在进行完最低位数的分配后再合并回单一的数组中。
基数排序算法的性能分析如下:
空间效率:一趟排序需要的辅助存储空间为r(r个队列),但以后的排序中重复使用这些队列,所以基数排序的空间复杂度为O(r)。
时间效率:基数排序需要进行d趟分配和收集,一趟分配需要O(n),一趟收集需要O(r),所以基数排序的时间复杂度为O(d(n+r)),它与序列的初始化状态无关。
稳定性:对于基数排序算法而言,很重要一点就是按位排序时必须是稳定的。因此,这也保证了基数排序保持稳定性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值