【数据结构】排序----归并排序和基数排序

归并排序和基数排序

归并排序

归并:把俩个或者多个有序的序列合并成一个。
m路归并,每选出一个元素需要对比关键字m-1次
代码实现:

int *B = (int *)malloc(n*sizeof(int));
//A[low..mid]和A[mid+1..high]各自有序,将俩个部分归并
void Merge(int A[],int low,int high){
    int i , j ,k;
    for(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[i++];//若第一个表未检测完,复制
    while(j<=mid)A[k++]=B[j++];//若第二个表未检测完,复制
}
void MergeSort(int A[],int low ,int high){
    if(low<high){
        int mid = (low+high)/2;//从中间划分
        MergeSort(A,low,mid);//对左右部分归并排序
        MergeSort(A,mid+1,high);//对右半部分归并排序
        MergeSort(A,low,mid,high);//归并
    }
}

2路归并排序算法的性能分析操作如下:
空间效率:Merge()操作中,辅助空间刚好为n个单元,所以算法的空间复杂度为O(n)。
时间效率:每趟归并的时间复杂度为O(n),共需进行log2n趟归并,所以算法的时间复杂度为O(nlog2n)。
稳定性:由于merge()操作不会改变相同关键字记录的相对次序,所以2路归并排序算法是一种稳定的算法。
一般而言,对N个元素进行k路归并排序时没排序的趟数m满足K^m=N,从m = logkN,又考虑到m为整数,所以m=logkN。这和前面的2路归并是一致的。

基数排序

假设长度为m的线性表中的每个结点aij的关键字由d元组(kj(d-1),kj(d-2),kj(d-3),…kj1,kj0)组成,其中,0<kji<=r-1(0<=j<n,0<=i<=d-1),r称为"基数"

基数排序得到递减序列的过程如下,
初始化:设置r个空队列,Qr-1,Qr-2,…Q0
按照各个关键字位权重递增的次序(个,十,百),对d和关键字位分别做“分配”和“收集”
分配:顺序扫描各个元素,若当前处理的关键字位=x,则将元素插入Qx队尾
收集:把Qr-1,Qr-2,…Q0各队列中的结点依次出队并链接

基数排序不是基于“比较的排序算法”,通常基于链式存储实现

typedef struct LinkNode{
    ElemType data;
    struct LinkNode *next;
}LinkNode,*LinkList;
typedef struct{//链式队列
    LinkNode *front,*rear;//队列的对头和队尾指针
}LinkQueue;

基数排序算法的性能分洗如下:
空间效率:一趟排序需要的辅助存储空间为r(r个队列:r个队头指针和r个队尾指针),但以后的排序中会重复使用这些队列,所以技术排序的时间复杂度为O®。
时间效率:基数排序需要进行d趟分配和收集,一趟分配需要O(n),一趟收集需要O®,所以以基数排序的时间复杂度为O(d(n+r)),它与序列的初始状态无关。
稳定性:对于基数排序算法而言,很重要一点就是按位排序时必须时稳定的。因此,这也保证了基数排序的稳定性。
基数排序擅长解决的问题:

  1. 数据元素的原剪子可以方便地拆分为d组,且d较小。反例:给五个人的身份证号排序
  2. 每组关键字的取值范围不大,即r较小。反序:给中文人名排序
  3. 数据元素个数n较大。擅长:给十亿人的身份证号排序。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值