📅  最后修改于: 2023-12-03 15:37:12.900000             🧑  作者: Mango
排序算法可以分为两类:
基于比较的排序算法的时间复杂度最好是O(n log n),这个下限是一个已经被证明的定理。而非基于比较的排序算法则可以做到线性或者接近线性的时间复杂度,但是由于其特殊的性质,只适合于特定的数据结构和数据类型。本文主要关注基于比较的排序算法。
一般情况下,排序算法的时间复杂度是决定其性能的因素。但是在实际应用中,我们也需要考虑时间复杂度以外的因素,比如存储空间和时间成本、实现难度、代码复杂度等等。
排序算法的存储器写次数可以通过模型进行估算,模型中存储器的使用可以分为三种情况:
按照这种模型进行计算,不同的排序算法的存储器写次数是不同的。比较经典的排序算法的存储器写次数如下所示(这里的N为数组长度):
算法 | 额外存储器 | 元素修改 | 元素移动 --- | --- | --- | --- 选择排序 | O(1) | O(N^2) | O(N^2) 冒泡排序 | O(1) | O(N^2) | O(N^2) 插入排序 | O(1) | O(N^2) | O(N^2) 希尔排序 | O(1) | O(N log^2 N) | O(N log^2 N) 归并排序 | O(N) | O(N log N) | O(N log N) 快速排序 | O(log N) | O(N log N) | O(N log N) 堆排序 | O(1) | O(N log N) | O(N log N)
从上表中我们可以看出,元素移动是占用存储器的最大因素,影响存储器写次数的最主要因素也是元素移动。对于算法的实现者来说,需要尽可能减少元素移动的次数。同时,这也是评判一个算法实现好坏的指标之一。
可以发现,归并排序和堆排序的额外存储器开销是较小的,利用的都是原始存储器中已有的元素。同时,在修改和移动元素方面,它们相对于其他算法都要优秀一些。因此,我们可以视归并排序和堆排序为那种排序算法使最少的存储器写次数的解决方案。
在实际应用中,对于排序算法的选用需要综合考虑各种因素。在时间复杂度和空间复杂度之间需要做出权衡。同时,对应用场景进行分析,看看能否针对性地实现某些特定的排序算法,以更好地满足需求。