808|知识总结|归并排序和基数排序

一、归并排序

(1)基本思想:将两个或两个以上的有序表合并为一个新的有序表。

(2)延展:二路归并——将一个序列R[0,...n-1]看作成两个序列R[0,...mid]和R[mid+1,...n-1],利用递归思想,再将R[0,...mid]和R[mid+1,...n-1]序列各自划分成两个序列,直到序列中元素个数为1,再进行两两归并排序,直到得到一个长度为n的有序序列。

(3)每趟排序的有序区都是局部有序,直到归并完成,才能算归位。

(4)算法

void Merge(Elemtype R[],int low,int mid, int high)
{
    Elemtype *B=(Elemtype *)malloc((high-low+1)*sizeof(Elemtype));   //定义一个B数组存放排序前的元素
    int i=low;
    int j=mid+1;
    int k;  
    for(k=low;k<=high;k++)   //将R数组的元素移动到B数组中
        B[K].key=R[k].key;
    k=i;
    while(i<=mid && j<=high)   //如果某一个序列扫描完毕则跳出比较,剩余的序列直接添加在有序区后
    {
         if(B[i].key<=B[j].key)      //比较谁更小,“=”确保稳定性
         {
           R[k].key=B[i].key;
           i++;              //注意i++是放在if语句里面的
         }
         else
         {
            R[k].key=B[j].key;
            j++;
         } 
         k++;       //k++可放在里面当if和else语句中都得有
    }
    while(i<=mid)    //剩余元素直接复制
         R[k++].key=B[i++].key;
    while(j<=high)
         R[k++].key=B[j++].key;
}

void MergeSort(Elemtype R[],int low,int high)
{
    if(low<high)   //递归思想,将一个大序列,划分为n个小序列
    {
       int mid=(low+high)/2;
       MergeSort(R,low,mid);
       MergeSort(R,mid+1,high);
       Merge(R,low,mid,high);
    }
}

(4)算法分析:

空间复杂度:B数组——n,递归工作栈——log2n,取大——O(n)

时间复杂度:需要进行h-1次排序,每次排序比较n次,则O(nlog2n)

稳定算法。

二、基数排序(一般考手算)

(1)基本思想:通过分配和收集来排序,分为最低位优先和最高位优先。

(2)思想过程:

1.将待排序链表的关键字按要求划分成d位数字组成,每一位数字表示关键字的一位,且每位的值都在0<=d<=r之内,其中r称为基数。

2.分配:开始时把Q0,...Qr-1各个队列置空,依次扫描线性表中的每一个元素,如果元素aj的关键词kji=k,则把元素插入Qk中。

3.收集:将Q0,...Qr-1队列中元素依次首尾相接,得到新的元素序列,从而组成新的线性表。

4.总共需要进行d趟。

5.每趟排序的有序区都是局部有序,直到归并完成,才能算归位。

(3)算法:

typedef struct node
{
       char data[MAXD];
       struct node *next;
}NodeType;

void RadixSort(Nodetype *&p,int r,int d)
{
    NodeTypee *head[MAXR],*tail[MAXR],*t;
    int i,j,k;
    for(i=0;i<=d-1;i++)
    {
       for(j=0;j<=r;j++)
          head[j]=tail[j]=NULL;
       while(p!=NULL)
       { 
            k=p->data[i]-'0';
            if(head[k]==NULL)
            {   
               head[k]=p;
               tail[k]=p;
            }
            else
            {
                tail[k]->next=p;
                tail[k]=p;
            }
            p=p->next;
       }
       p=NULL;
       for(j=0;j<=r;j++)
       {
          if(p==NULL)
          {
             p=head[j];
             t=tail[j];
          }
          else
          {
             t->next=head[j];
             t=tail[j];
           }
        }
        t->next=NULL;
    }
}

(4)算法分析:

时间复杂度:O(d(n+r))

空间复杂度:O(r)

稳定的排序方法。

三、错题总结

1.李春葆例题

2.王道选择题

(1)将两个各有n个元素的有序表合成一个有序表,最少比较次数为N(第一个有序表最大值比第二个有序表最小值小),最多比较次数为2n-1(两个有序表大小交替出现)。

(2)对数据文件进行排序,使用的方法是归并排序。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值