内部排序算法要点总结

版权声明:本文为博主原创,转载请注明出处 https://blog.csdn.net/fireflylane/article/details/84477138

  本文将对于插入排序、冒泡排序、选择排序、希尔排序、归并排序、快速排序、堆排序、分配排序和基数排序做归纳总结,通过一些题目来掌握各大内部排序算法的过程和特点,而不涉及具体的代码。

考点

  1. 排序算法的稳定性(题1)
  2. 排序算法的空间效率(题2)
  3. 特殊数据下排序算法的效率比较 / 算法的最差、平均、最佳情况(题3、8、9)
  4. 排序算法的执行过程(题4、5、6、7、10)

习题

1、当排序的序列存在多个具有相同关键码的记录时,经过排序后,如果这些记录的相对顺序仍然保持不变,则这个排序算法称为是稳定的。八种内部排序法哪些是稳定的,如果不稳定,如何修改使之稳定?
【答案】
插入排序、冒泡排序是稳定的。 因为元素交换当且仅当元素大小为严格的不等关系。
选择排序不稳定。 因为它仅当当前元素比目前最小元素小时才重新设定最小元素值,但是检索是从数组末尾开始的,所以可能会出现相同值的元素顺序改变。对于这个算法只需将选择最小关键码的条件从”小于”改为”小于等于”即可。
希尔排序不稳定。 因为子表的排序是互相独立的,很可能在子表中发生的交换使得一个元素移到了与它等值的元素的前面。
快速排序不稳定。 选择好枢纽后将枢纽与数组中最后一个元素交换,这个过程是不需要条件的,可能恰好交换了两个值相同的元素。
归并排序理论上是稳定的。 但是它的数组实现不稳定,当两个子表的第一个元素相同时,归并操作会优先选择其中一个子表的元素。只需将选择的条件从“小于”改为“小于等于”即可。
堆排序不稳定。 左右子树的元素的处理时相互独立的,这很可能使得元素原来的相对位置发生改变。
分配排序是稳定的。 相同的元素总是被添加到列表的末尾,不发生次序的变化。
基数排序是稳定的。 因为桶的填充过程和处理序列取出元素过程都是自底向上的,保持了相对顺序。

2、在下列排序算法中,所需辅助存储量最多的是()
A) 快速排序 B) 归并排序 C) 堆排序 D) 链式基数排序
【分析】
  由于快速排序和堆排序是原地排序,不需要辅助数组,故排除。归并排序只需要与原数组等大的辅助数组即可,链式基数排序每位数排序时都需要开辟与原数组数目相同的链表结点空间,所需辅助存储量最多,故选D。
原地排序
  指基本上不需要额外辅助的的空间,允许少量额外的辅助变量进行的排序。就是在原来的排序数组中比较和交换的排序。像选择排序,插入排序,希尔排序,快速排序,堆排序等都会有一项比较且交换操作(swap(i,j))的逻辑在其中,因此他们都是属于原地(原址、就地)排序,而合并排序,计数排序,基数排序等不是原地排序。

3、在文件“局部有序”或文件长度较小的情况下,最佳内部排序的方法是()
A) 直接插入排序 B) 冒泡排序 C) 简单选择排序 D) 基数排序
【分析】
比较一下插入排序、冒泡排序、选择排序:

插入排序 冒泡排序 选择排序
k轮后前k个元素有序 k轮后前k大(小)的元素已排好 k轮后前k大(小)的元素已排好
排序可以提前结束,如果数组已然有序只需要O(n)的时间复杂度 排序不可提前结束(最佳情况仍为O(n^2)) 排序不可提前结束

由上,此题选A。

【补充】
交换排序算法的关键瓶颈是比较操作次数,时间复杂度统计的是比较操作次数

比较情况 插入排序 冒泡排序 选择排序
最佳情况 O(n) O(n^2) O(n^2)
平均情况 O(n^2) O(n^2) O(n^2)
最差情况 O(n^2) O(n^2) O(n^2)

交换操作可以决定一个算法实际效率

交换情况 插入排序 冒泡排序 选择排序
最佳情况 0 0 O(n)
平均情况 O(n^2) O(n^2) O(n)
最差情况 O(n^2) O(n^2) O(n)

4、数据表中有10000个元素,如果仅需求出其中最大的10个元素,则采用()排序算法最节省时间。
A) 快速排序 B) 希尔排序 C) 堆排序 D) 选择排序
【分析】
挑选10个最大的元素故聚焦堆排序和选择排序,由于堆排序是O(nlogn),选择排序是O(n^2),故选C。

5、数据序列(8,9,10,4,5,6,20,1,2)只能是下列排序算法中的()两趟排序后的结果。
A) 选择排序 B) 冒泡排序 C) 插入排序 D) 堆排序
【分析】
  根据前面的总结,冒泡排序和选择排序的两轮排序后前两个元素是一样的,插入排序与前两者的区别就在于它只保证了有序,但无需是最大的或最小的。所以由于前两个元素是升序排序,如果是冒泡或者是选择那么前两个元素应该是整个数组中最小的两个元素,显然不对,故选C。

6、对一组数据(84,47,25,15,21)排序,数据的排列次序在排序的过程中的变化为
(1) 84 47 25 15 21 (2) 15 47 25 84 21 (3) 15 21 25 84 47 (4) 15 21 25 47 84
则采用的排序是()
A) 选择排序 B) 冒泡排序 C) 快速排序 D) 插入排序
【分析】
  观察知,排序可能为冒泡或选择,选择和冒泡的区别主要在于一轮排序中的交换次数,所以只需观察排序过程中序列的变化程度就能做出判断。具体的看,选择排序在每轮只发生一次交换,观察序列知此题选A。

7、对序列(15,9,7,8,20,-1,4)进行排序,进行一趟后数据的排列变为(4,9,-1,8,20,7,15);则采用的是()排序。
A) 选择排序 B) 快速排序 C) 希尔排序 D) 冒泡排序
【分析】
  希尔排序需要知道缩小增量是多少故不选。选择排序和冒泡排序都要求局部排好,而一轮过后的序列的第一个元素既不是最大也不是最小,故不选。所以选C。可以发现pivot大概选择的是8。

【补充】希尔排序
  Shell排序是这样进行分组和排序的:把序列分成多个“虚拟”子序列然后分别对子序列进行排序。子序列的排序则利用插入排序。
  分割子序列的具体方法是从整个数组中等间距地抽取元素。每轮排序都会缩小间距(增量)。
  选择适当的增量序列可以使Shell排序比其他排序方法更有效率。一般来说增量序列为(2k,2k-1,…,2,1)时2并无多大效果,而“增量每次除以3”更好。
  希尔排序的时间复杂度为O(n^1.5),可能有疑问是,如果Shell排序总是以一个常规的插入排序结束,又怎会比插入排序的效率更高?希尔排序希望经过每次对子序列的处理,可以使待排序的数组更加有序,当最后一轮调用插入排序时,数组已经是基本有序的了,并产生一个相对花费时间较少的最终插入排序(前文有提到插入排序提前结束的性质)。
注:当数据规模中等时,希尔排序具有很好的效率。

8、下列排序算法中,在待排序数据已有序时,花费时间反而最多的是()排序。
A) 冒泡排序 B) 希尔排序 C) 快速排序 D) 堆排序
【分析】
  考察各内部排序算法的最差情况,快速排序的退化。选C。
【快速排序的退化】
  快速排序是迄今为止所有内部排序算法中在平均情况下最快的一种。相比于归并排序,快速排序不需要额外的数组空间,因此空间效率也很高。但有意思的是,快速排序往往由于最差时间代价而在某些应用中无法采用。
  快速排序最差情况出现在轴值未能很好地划分数组的时候,即一个子数组中没有结点,而另一个数组中有n-1个结点。在这种情况下,分治策略未能很好地完成划分任务。因此,下一次处理的子问题规模只比原问题的规模减少了1个元素。如果这种情况发生在每一次划分过程中,那么算法的总时间代价为O(n^2)。由于递归调用的时间开销,这甚至比冒泡排序更糟糕

9、对初始状态为递增序列的表按递增顺序排序,最省时间的是()算法,最费时间的是()算法。
A) 归并排序 B) 快速排序 C) 插入排序 D) 堆排序
【分析】
  考察排序算法处理特殊数据的效率。选C ; B。

10、几种重要排序算法的过程
【堆排序】

题目:将整数数组(7-6-3-5-4-1-2)按照堆排序的方式原地进行升序排列,请问在第一轮排序结束后,数组的顺序是()

A.2-6-3-5-4-1-7

B.6-2-3-5-4-1-7

C.6-5-3-2-4-1-7

D.1-5-3-2-4-6-7

E.5-4-3-2-1-6-7

F.5-1-3-2-4-6-7


答案:C


解析:因为是原地进行升序排列,所以应该是建立大根堆;如果是原地进行降序排列,应该建立小根堆。

第一步:先建立大根堆,因为给定的数组就是大根堆,所以就不需要建立大根堆了。大根堆图如下:


第二步:堆建好之后开始排序,堆顶就是最大值,取出放入数组中的最后一个位置,将堆底(数组中的最后一个元素)放入堆顶。因为这一操作会破坏堆,需要将前n-1个元素调整为堆。这样一轮排序就结束了。


调整为大根堆之后:



所以在第一轮排序结束后,数组的顺序是:6-5-3-2-4-1-7


题目2:给出一组关键字T=(12,2,16,30,8,28,4,10,20,6,18)。写出用下列算法从小到大排序时第一趟结束时的序列。
【希尔排序】(第一趟排序的增量为6)

答案:(4,2,16,6,8,28,12,10,20,30,18)

【快速排序】(选第一个记录为枢轴)
先交换第一个元素和最后一个元素,再用两个指针从头和尾向中间并拢,分别找大于轴值的元素和小于轴值的元素,都找到了则交换,直至两个指针指向同一个元素(右部的首元素),返回左指针的值,并将该位置的元素和尾元素交换,一轮排序完毕。
答案:(6,2,10,4,8,12,30,16,20,18,28)

题目:将整数数组(7-6-3-5-4-1-2)按照堆排序的方式原地进行升序排列,请问在第一轮排序结束后,数组的顺序是()

A.2-6-3-5-4-1-7

B.6-2-3-5-4-1-7

C.6-5-3-2-4-1-7

D.1-5-3-2-4-6-7

E.5-4-3-2-1-6-7

F.5-1-3-2-4-6-7


答案:C


解析:因为是原地进行升序排列,所以应该是建立大根堆;如果是原地进行降序排列,应该建立小根堆。

第一步:先建立大根堆,因为给定的数组就是大根堆,所以就不需要建立大根堆了。大根堆图如下:


第二步:堆建好之后开始排序,堆顶就是最大值,取出放入数组中的最后一个位置,将堆底(数组中的最后一个元素)放入堆顶。因为这一操作会破坏堆,需要将前n-1个元素调整为堆。这样一轮排序就结束了。


调整为大根堆之后:



所以在第一轮排序结束后,数组的顺序是:6-5-3-2-4-1-7


猜你喜欢

转载自blog.csdn.net/fireflylane/article/details/84477138
今日推荐