《关于排序,你应该知道的》


一、关于排序的几个概念

(1)数据表 :待排序数据元素的有限集合。

(2)排序码(也常称为“关键字”) :数据元素中通常不止含有一个属性域(即数据成员),选定其中一个属性域作为排序的依据。该域称为排序码。

(3)主排序码 :数据表中各个数据元素的排序码互不相同,这种排序码为主排序码。
(如果按照主排序码进行排序,排序结果是唯一的)

(4)次排序码 :数据表中有些数据元素的排序码相同,这种排序码为次排序码。
(如果按照次排序码进行排序,排序结果不是唯一的)


二、什么是排序

(1)“通俗”的定义
排序就是将一组杂乱无章的数据按一定的规律顺序排列好。

(2)精确定义
设含有n个元素的序列为R [0] , R [1] , ..., R [n-2] , R [n-1], 其相应的排序码序列为K [0] , K [1] , ..., K [n-2] , K [n-1]。 排序,就是确定n个数字0,1,...,n-1的一种排列p [0] , p [1] , ..., p [n-2] , p [n-1],使得各个排序码满足如下的非递减关系(或非递增关系):
K [p[0]]   <=   K [p[1]] <= ...<= K [p[n-2]] <= K [p[n-1]] 或 K [p[0]]   >=   K [p[1]] >= ... >= K [p[n-2]] >= K [p[n-1]]


三、排序算法的分类(分类依据:数据元素是否完全在内存中)

(1)内部排序 :内部排序是指排序期间数据元素全部存放在内存中的排序。(适合于不太大的元素序列)
(内部排序的过程是一个逐步扩大记录的有序序列长度的过程。)





(2)外部排序 外部排序指的是大文件的排序,即待排序的记录存储在外部存储器上,待排序的文件无法一次装入内存,需要在内存和外部存储器之间进行多次数据交换,以达到排序整个文件的目的。
(外部排序中最常用的算法是多路归并排序,即将原文件分解成多个能够一次性装入内存的部分,然后分别把每一部分调入内存完成排序)


四、排序算法的分类(分类依据:数据元素的物理位置在排序过程中是否改变)

(1)静态排序 :通过修改数据元素的指针,而各个数据元素的物理位置不变化来排序。

(2)动态排序 :通过改变数据元素的物理位置来排序。


五、 排序算法的分类(分类依据:算法的稳定性)

(1)稳定的排序算法 若存在多个具有相同排序码的记录,经过排序之后,这些记录的相对次序仍然保持不变,则这种排序算法称为稳定的排序算法。




(2)不 稳定的排序算法 若存在多个具有相同排序码的记录,经过排序之后,这些记录的相对次序发生改变,则这种排序算法称为不稳定的排序算法。





六、排序算法的分类(分类依据: 平均时间复杂度

(1) 平方阶 O(n 2 )
一般称为简单排序,如直接插入排序,选择排序,冒泡排序。

(2) 线性对数阶  O(nlgn)
如快速排序,堆排序,归并排序。

(3)O(n 1+ ԑ )[其中0<ԑ<1]
如希尔排序。

(4)O(n)
如桶排序,基数排序。

七、各种常见排序算法的时间复杂度和空间复杂度(及稳定性)



八、时间复杂度函数的增长情况




九、 根据以下因素并结合实际选择合适的排序算法
(1)待排序的元素个数
(2)元素本身数据量的大小,也就是元素中除关键字外的其他信息量的大小
(3)关键字的结构及其分布情况
(4)对排序稳定性的要求
(5)语言工具的条件
(6)所用的存储结构
(7)时间复杂度
(8)(辅助)空间复杂度


十、各种常见排序算法小结

(1)直接插入排序

1、算法运行时间与待排序元素的原始排列顺序有关。

2、对于规模很小的待排序元素序列(n<=25)非常有效。

3、主要用于待排序元素个数不是很大(<10k)的情况。


(2) 折半插入排序(二分法插入排序)

1、  折半搜索比顺序搜索快,故在平均性能上 折半插入排序快于 直接插入排序。

2、当待排序元素已按排序码排好序或接近有序时,直接插入排序比折半插入排序执行的排序码比较次数要少。

3、折半插入排序的元素移动次数与直接插入排序相同,且都与 待排序元素的原始排列顺序有关。


(3)希尔排序(Shell排序、缩小增量排序)

1、对于中等规模的待排序元素序列(n<=1000),希尔排序有很高的效率。

2、 希尔排序的时间复杂度分析很难,排序码的比较次数与元素移动次数依赖于“增量因子序列”的选取,特定情况下可以准确估算出排序码的比较次数和元素的移动次数。目前还没有人给出选取最好的增量因子序列的方法。增量因子序列可以有各种取法,有取奇数的,也有取质数的,但需要注意:增量因子中除1 外没有公因子,且最后一个增量因子必须为1


(4) 冒泡排序(起泡排序)

1、改进的冒泡排序算法在最好情况下对于n个元素的排序只需一趟冒泡过程就可以完成,此时只需n-1次比较操作。

2、 主要用于待排序元素个数不是很大(<10k)的情况。

(5) 快速排序(分区排序)

1、是目前应用最广泛的排序算法,也是最通用的高效的内部排序算法。

2、快速排序在空间上只使用一个小的辅助栈,内部循环很小,容易实现。

3、待排序元素个数n,当n较大时,在平均情况下快速排序是“快速”的,但当n很小时,快速排序一般慢于其他简单排序方法。

4、适用于 待排序元素个数n很大的情况。

5、 当待排序的元素是随机分布时,快速排序的平均时间最短。

6 、当待排序元素序列 有序或接近有序时,快速排序反而退化为冒泡排序。为改进之,通常以“三者取中法”来选取基准记录,即选取排序区间的两个端点与中点这三个元素的排序码中的中间值做为基准记录。

(6) 归并排序

1、 算法运行时间与待排序元素的原始排列顺序无关,每次划分产生的两个子序列的长度基本相同,故其最好、最坏和平均时间复杂度都是O(nlgn)。

2、主要缺点是它需要一个与待排序元素数组一样大的辅助数组空间,需要O(n)的附加内存空间。虽有方法克服这个缺点,但其代价是会使算法变得很复杂且时间复杂度会增加,故实际应用中一般不提倡这样做。

3、 适用于 待排序元素个数n很大的情况。

(7) 直接选择排序:

1、直接选择排序的排序码比较次数与待排序元素的 原始排列顺序无关,元素的移动次数与 待排序元素的 原始排列顺序有关。

2、相对于其他排序算法,待排序元素的原始排列顺序(有序性)对于直接选择排序的运行时间影响不大。因为从未排序部分的元素中选择出最小元素的每步操作过程,没有对下一步要找的最小元素的位置给出相关信息。

3、直接选择排序对于已排好序、接近有序、随机排列的待排序元素序列所花时间基本相同,故执行时间比较固定。

4、直接选择排序对于一种元素序列有较好的效率----元素规模很大,而排序码较小的元素序列。因为对这种序列进行排序,移动操作所花费的时间远大于比较操作所花费的时间,而其他排序算法的 移动操作次数 都比直接选择排序大得多。

5、 主要用于待排序元素个数不是很大(<10k)的情况。

(8) 锦标赛排序(树形选择排序)

1、克服了直接选择排序中的缺点,已经不是像直接选择排序那样经常把前一趟已经做过的比较又重新做了一遍,而是改成将 前一趟比较的结果保留了起来,供后一趟的比较操作使用。

(9) 堆排序

1、是一种高效的内部排序算法,没有什么最坏情况会导致堆排序的运行时间明显变慢,基本不需要额外的空间。但它不大可能提供比快速排序更好的平均性能。

2、 适用于 待排序元素个数n很大的情况。

(10) 桶排序(箱排序)
1、 缺点是:空间复杂度比较高,需要的额外开销大。排序中有两个数组的空间开销,一个存放待排序数组,一个是所谓的桶;其次,待排序的元素都要在一定的范围内。

(11) 基数排序

1、它不仅对元素序列的排序码进行比较,还对排序码的不同部分进行处理和比较,虽然其时间复杂度为线性增长,但由于在常规的编程环境中,关键字索引统计程序内部循环中包含大量操作,其数目比快速排序或归并排序的内部循环要多得多,故基数排序的线性时间开销实际上不比快速排序的时间开销小很多。而且由于基数排序基于的排序码抽取算法受到操作系统和排序元素的影响,导致其适应性不及普通的比较和交换操作。

2、在硬件环境、编程环境和输入元素序列满足一定条件时,基数排序可以达到很高的效率。

3、考虑到基数排序过程中使用额外的计数和额外的存储空间(与待排序元素序列规模相同的存储空间和与基数数目相等的一系列计数器),基数排序不适用于规模很小的待排序元素序列。

4、它的局限性:排序码可分解;元素的排序码位数较少,如果密集更好;如果排序码是数字,最好是无符号的,否则将增加相应的映射复杂度,可先将其正负分开排序。

十一、不同排序算法的选择策略

(1)简单排序中直接插入最好,快速排序最快,当文件为正序时,直接插入和冒泡均最佳。

(2)当元素个数 n较小时(如n≤50),可选用直接插入排序、直接选择排序。

(3)当 文件初始状态基本有序(指正序),可选用直接插入排序、冒泡排序、随机的快速排序。

(4)当元素个数 n较大时,可选用时间复杂度为O(nlgn)的排序方法: 快速排序,堆排序,归并排序

(5) 堆排序 (不稳定) 所需的辅助空间少于快速排序,并且不会出现快速排序可能出现的最坏情况。

(6) 通常可以将 归并排序 和直接插入排序结合在一起使用。先利用直接插入排序求得若干个较长的有序子序列,然后再两两归并之。因为直接插入排序是稳定的,原本的归并排序也是稳定的,所以改进后的归并排序仍是稳定的。

(7) 当原表有序或基本有序时,直接插入排序和冒泡排序将大大减少比较次数和移动元素的次数,时间复杂度可降至On);而快速排序则相反,当原表基本有序时,将退化为冒泡排序,时间复杂度提高为O(n2)原表是否有序,对直接选择排序、堆排序、归并排序和基数排序的时间复杂度影响不大。

(8) 一般不使用或不直接使用传统的冒泡排序。




猜你喜欢

转载自blog.csdn.net/wuchangi/article/details/78939638