一 概述
衡量某种算法对于某类数据进行处理更加好时,往往会从算法的时空复杂度,算法的稳定性,算法的过程特征等因素来进行分析。
二 从时间复杂度分析
简单选择排序,直接插入排序和冒泡排序平均情况下的时间复杂度都为O(n^2),且实现过程相对比较简单,当直接插入排序和冒泡排序最好情况下的时间复杂度可以达到O(n),而简单选择排序则于序列的初始状态无关,这三种均为稳定的排序算法。
希尔排序作为插入排序的拓展,对于较大规模的排序都可以达到比较高的效率,但目前未得出其精确的渐进时间,且其为一种不稳定的排序算法。
堆排序利用了一种称为堆的数据结构,可以在线性时间内完成建堆,且在O(nlog2^n)时间内完成排序过程,堆排序为一种不稳定的排序算法。
快速排序基于分治的思想,虽然最坏的情况下快速排序时间达到O(n^2),但快速排序平均性能可以达到O(nlog2^n),在实际应用中常常优于其他排序算法,快速排序是一种不稳定的排序。
归并排序同样采用了分治的思想,但是由于其分割序列于初始序列的排列无关,因此它的最好,最坏和平均时间复杂度均为O(nlog2^n),归并排序是一种稳定的排序。
三 从空间复杂度分析
简单选择排序,插入排序,折半插入排序,希尔排序,冒泡排序和堆排序都只需要借助常数个辅助空间,可以将它们的空间复杂度理解为原地空间复杂度。
快速排序在空间上需要一个辅助栈,用于方法的递归实现。平均情况下大小为O(log2^n),当然在最坏的情况下可能会增长到O(n)。
归并排序在合并操作中需要借助较多的辅助空间用于元素复制,大小为O(n),虽然有方法可以规避该问题,但是其代价时算法会复杂很多,而且时间复杂度会增加。
四 从稳定性分析
插入排序,折半插入排序,冒泡排序,归并排序和基数排序均为稳定的排序方法,而简单的选择排序,快速排序,希尔排序和堆排序都是不稳定的排序方法。
五 从过程特征分析
采用不同的排序算法,在一次循环或几次循环后的排序结果可能是不同的,所以根据这些排序的不同结果进行过程特征分析来判断使用的算法种类。
六 内部排序算法的选择和应用
选择排序算法需要考虑的因素:
- 待排序的元素数目n。
- 元素本身的信息量的大小。
- 关键字的结构及其分布情况(如基数排序关键字)。
- 稳定性的要求,对稳定性要求较高时选择稳定的排序算法,如冒泡排序或者归并排序等。
- 算法实现的语言工具条件,存储结构及辅助空间的大小等。
七 内部排序算法的总结
- 若n较小时,可采用直接插入排序或者简单选择排序。由于直接插入排序所需的记录移动次数较简单选择排序多,因此当记录本身信息量较大时,用简单选择排序比较好。
- 若待排序序列的初始状态已经基本有序的时候,比较适合选用直接插入或冒泡排序,在该种情况下它们的时间复杂度为O(n)。
- 当待排序的序列数据规模n较大的时候,则应该采用时间复杂度为O(nlog2^n)排序方法:如归并排序,堆排序,快速排序。快速排序方法为基于比较的内部排序方法中最好的方法,当待排序的关键字随机分布时,快速排序的平均时间最短。堆排序所需的辅助空间(O(1))少于快速排序(O(log2^n))和归并排序(O(n)),并且不会出现快速排序可能出现的最坏情况,三者中只有归并排序为稳定的排序方法,所以要求时间复杂度为O(nlog2^n)且稳定的排序方法时就可以直接选择归并排序。实际应用中直接使用归并排序的效果并不理想,通常可以将它于直接插入排序结合起来使用。先利用直接插入排序求得较长的有序子序列,然后进行归并排序。直接插入排序算法时稳定的算法,所以直接插入排序+归并排序的算法组合也是稳定。
- 当待排序的序列数据规模较大的时候,记录的关键字位数较少且可以分解时,采用基数排序比较好。
- 当待排序的序列中记录本身的信息量较大时,为例避免耗费大量的时间移动记录,可以用链表作为存储结构,同时选择支持链式存储的排序算法,如冒泡排序,堆排序,简单选择排序,快速排序,直接插入排序等适用于链式存储结构的排序算法。此时移动数据时只需要改变指针的指向即可,避免了大数据量的转移。
- 在基于比较的排序算法中,每次比较两个关键字的大小后,仅出现两种转移的情况。因此可以用一棵二叉树来描述比较判定过程,所以当序列中的n个关键字随机分布时,任何借助于"比较"的排序算法,只要需要O(nlog2^n)的时间,如归并排序,快速排序,堆排序等。