这是我参与「第三届青训营 -后端场」笔记创作活动的的第11篇笔记
1. 为什么要学数据结构和算法
2. 经典排序算法
2.1 插入排序
2.2 快排
2.3 堆排序
3. 从零开始打造pdqsort
3.1 pdqsort
3.2 pdqsort-version1
结合三种排序方法的优点
- 对于短序列(小于一定长度)我们使用插入排序
- 其他情况,使用快速排序来保证整体性能
- 当快速排序表现不佳时,使用堆排序来保证最坏情况下时间复杂度仍然为O(n*logn)
\
3.3 pdqsort-version2
思考关于pivot的选择
- 使用首个元素作为pivot(最简单的方案)
- 实现简单,但是往往效果不好,例如在sorted情况下性能很差
- 遍历数组,寻找真正的中位数
- 遍历比对代价很高,性能不好
还有什么场景我们没有优化?
-
短序列情况
- 使用插入排序(v1)
-
极端情况
- 使用堆排序保证算法的可行性(v1)
-
完全随机的情况(random)
- 更好的pivot 选择策略(v2)
-
有序/逆序的情况(sorted/reverse)
- 根据序列状态翻转或者插入排序(v2)
-
元素重复度较高的情况(mod8) -> ?
3.4 pdqsort-final version
如何优化重复元素很多的情况?
- 采样pivot的时候检测重复度? 不是很好,因为采样数量有限,不一定能采样到相同元素
- 解决方案: 如果两次partition 生成的pivot相同,即partition 进行了无效分割,此时认为pivot的值为重复元素(相比上一种方法有更高的采样率)
优化-重复元素较多的情况(partitionEqual)
- 当检测到此时的pivot和上次相同时(发生在leftSubArray)使用partitionEqual将重复元素排列在一起,减少重复元素对于pivot选择的干扰
优化-当pivot选择策略表现不佳时,随机交换元素
- 避免一些极端情况使得QuickSort总是表现不佳,以及一 些黑客攻击情况
\