稳定性
-
稳定性解释
同样值的个体之间,如果不因为排序而改变相对次序,就是这个排序是有稳定性的,否则就没有。
不具备稳定性的排序:
选择排序、快速排序、堆排序具备稳定性的排序:
冒泡排序、插入排序、归并排序、一切桶排序思想下的排序目前没找到时间复杂度O(n*logn),而外空间复杂度O(1),又稳定的排序
-
示例说明
将【3 3 3 3 3 1 3 3 3 3 3 】排序,选择排序中,
第一轮将下标[0]和[5]做了交换,得到【1 3 3 3 3 3 3 3 3 3 3 】,但是一开始下标0的3排到了下标 1 2 3 4的后面去了,这就破坏了原先的相对次序。
其他算法也可依次证明。 -
用处
比如大二计算机课程的期末成绩已经按照考勤分排了一次,A同学考试成绩60,考勤16,B同学考试成绩60,考勤15,。然后用(选择排序、快速排序、堆排序)排总分的时候,有可能A同学反而排在B同学后面,这就很不友好了。
总结
排序 | 时间复杂度 | 空间复杂度 | 稳定性 |
---|---|---|---|
选择 | O(N^2) | O(1) | × |
冒泡 | O(N^2) | O(1) | √ |
插入 | O(N^2) | O(1) | √ |
归并 | O(N*logN) | O(N) | √ |
快排 | O(N*logN) | O(logn) | × |
堆排 | O(N*logN) | O(1) | × |
- 一般来说,都是用快排。
- 归并排序可以做到空间复杂度为O(1)吗,可以!但是就不再稳定了。而且实现非常难,不如用堆排序。
- “原地归并排序”方法会让时间复杂度变成O(n^2)也不行,不如插入排序。
- “01 stable sort”论文的方法可以实现快排的稳定性,但是会让空间复杂度变成O(n)水平,不如直接用归并。
- 所有的改进都不重要,因为目前没有找到时间复杂度为O(N*logN),额外空间复杂度O(1),又稳定的排序。
- 有一道题目,是奇数放在数组左边,偶数放在数组右边,还要求原始的相对次序不变,碰到这个问题,可以怼面试官。 按照经典快排,这个问题跟左边小于等于一个数和右边大于一个数是等效的,但是无法做到稳定性,你可以直接让面试官教下你(左神都说超级难实现)。
- 工程上充分利用O(N*logN)和O(N^2)的优势,如快排递归到样本量小于六十的时候,用插入排序更快。
- 工程上利用稳定性优势,如果是基础类型数据的排序,如 年龄,分数,用快排。如果是用户自己定义的类型,职工(年龄、工时等属性)用归并。
- 而C++和java等语言的排序,底层实现都非常多代码,用到了很多排序,充分利用各种排序的优势。