数据结构-第八章(8.5归并排序和基数排序)

复习提示:这一章大致看看,直接做题,更高效。

1.归并排序

思想:归并排序与基于交换、选择等排序的思想不一样,“归并”的含义是将两个或两个以上的有序表合并成一个新的有序表。

  • 二路归并排序: 现有n个记录的待排序表,将其视为n个长度为1的有序表,然后两两归并,得到长度为n/2个长度为2的有序表(当n为奇数时还要额外得到1个长度为1的有序表);继续两两归并……如此重复,直到合并成一个长度为n的有序表为止。

考题:排序过程中比较次数的数量级与排序初始状态无关的是归并排序

过程:

两个有序表归并,我们可以用两个下标指示有序表的表头,然后我们比较下标处的记录大小,将小的记录转移到一个辅助数组TmpA[],并后移相应下标,这样我们通过循环就能将两个有序表中的记录转移到辅助数组中并成为一个新的有序表。 

利用分治的思想解决整个序列排序,那我们很自然地想到函数递归:

  • 归并排序需要的最大额外空间都为辅助数组空间的n个单元,所以空间复杂度为O(n)。
  • 二路归并排序我们一共需要[logn]趟归并,注意这里将n个长度为1的子表归并得到n/2个长度为2的有序表为一趟归并。每趟归并的时间复杂度都是O(n)这个数量,所以二路归并排序的时间复杂度为O(nlogn)。(作为一个必记的二级结论)

考题:2路归并排序中,归并趟数的数量级是O(nlog2的n次)

  • 归并过程中我们在代码中规定了左半部分和右半部分记录相同时让左半部分先转移,(多路也会有类似规定)所以归并排序是稳定排序。
  • 归并排序是内排序方法的一种,而且外部排序中也使用到了归并排序。所以归并排序既属于内排序也属于外排序

2.基数排序

总览

理解:按照自己的理解就是纯数学的规则,按照规则办事。这时候就与链式结合起来,以一种玩的心态记忆和写这些规则,反而对这些知识点可以更好的深刻理解。

基数排序很特别,它不直接比较关键字的大小进行排序,而且比较关键字各个元的大小进行排序。基数排序是一种借助多关键字排序的思想对单逻辑关键字(各个位逻辑相同,即基数相同)进行排序的方法。

关键字通常是多元的,比如十进制数684就有三个元,百位、十位、个位。其中百位就是权重最大的最主位关键字,个位是权重最小的最次位关键字。其中每一位有多少种可能称为基数r,如十进制数基数为10,二进制数基数为2。

实现多关键字排序有两个方法:假设共有d个元(,,...,)

最高位优先(MSD)法:先根据权重更大的位 去给我们建立的基数个子序列排序,将得到的每个序列按进行排序又各自划分成基数个子序列,按此操作,最后将所有子序列依次连接成一个有序序列。
最低位优先(LSD)法:先根据权重最小的位去排得到一个序列,然后按更大权重的位去排这个序列,按此操作,最后得到一个有序序列。
基数排序是对单逻辑关键字(各个位逻辑相同,即基数相同)进行排序的,那么这时用LSD法就更为方便,只需从最低位起,把关键字分配到r个队列中然后收集之,如此重复d次。下面四个图描述了这个过程。

  1. 分配:开始时,把r个队列全部置成空队列,然后依次考察线性表中的每个结点,若结点该位关键字为k,则放到队列中。
  2. 收集:把这个r个队列中的结点依次首尾相接,得到新的结点序列,从而组成新的线性表。

 

 

 

空间复杂度:前面已经说了基数排序通常是基于链式存储实现的,我们设置的链队列只包含了一个队头指针和一个队尾指针,队列的结点是我们待排序列中的结点,所以队列不额外开辟结点空间。基数排序的空间复杂度为O(r),注意此处问题规模是r,并不是结点个数n。
时间复杂度:一趟分配是O(n),一趟收集是O(r),共计d趟分配、收集,所以基数排序的时间复杂度为O(d(r+n))。注:n为关键字个数,d为把关键字分为了多少个元,r为每个元有多少种取值
稳定性分析:两个相同的关键字,排在前面的分配时先进队列,收集时先出队列,顺序没有改变,所以基数排序是稳定排序。基数排序的每一趟必须都是稳定的,因为我们每一趟比较的都是某一个位的大小,对于这一位相等,它的上一位不一定相等,不能被打乱。比如有{25,32,34,},排个位之后为{32,34,25},排十位用不稳定就会为{25,34,32}。
基数排序擅长解决的问题:

数据元素个数n很大。
数据元素的关键字有为d位分主次的元,且d较小。
每位元的取值范围不大,即基数r较小
下面的思想需要理解:

计数排序:计数待排序列中每个元素出现的次数,并把每个元素的数量都记录下来。比如待排序列为{5,4,3,2,2},我们创造一个长度为5-2+1的数组(即最大值减最小值加1,保证每个元素都有地方去计数),然后我们遍历待排序列后数组中就有二个2,一个3,一个4,一个5这样的信息了,我们就输出2,2,3,4,5这个排好的序列了。该过程也不是基于比较的排序算法,以空间换时间,时间复杂度为O(n)。我们可以看出基数排序每一趟其实类似一次计数排序,只不过统计的不是元素的数量而是元素本身。

桶排序:将数组分到有限数量的桶子里,每个桶子再分别排序(有可能是使用别的排序算法或者继续使用桶排序递归地进行排序)。该过程对输入的数据作了某些假定,所以时间复杂度比基于比较的排序算法时间复杂度低,属于是空间换时间了。很显然基数排序(MSD)就是桶子里继续使用桶排序递归地进行排序。而基数排序(LSD)是先分到桶子里,但是桶子内部不排序就收集出来,再分配再收集直到完成排序。

总结:基数排序、桶排序、计数排序都不是基于比较的排序算法,它们都以空间消耗提升换取了时间消耗减少。它们都是在某方面作了假定再进行排序,所以个人认为抽象一下其思想都是类似的。

单逻辑关键字的理解:单逻辑关键字每一位都是相同的逻辑,比如我们基数排序时要排的整数的每一位都是十进制的逻辑。这样我们进行基数排序时可以设置基数r个反复使用的队列。如果不是单逻辑而是每一位都有它自己的逻辑,比如52张牌,面值位基数为12,花色位基数为4。那么就演变成了多关键字排序。这就和“基数排序是一种借助多关键字排序的思想对单关键字进行排序的方法”这句官方概述相同。

 一道题检验:

 

注:注意分配和收集的位置顺序,一定要明确。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值