1、常用的三大排序:
插入排序,快速排序,堆排序
可以考虑排列的随机度,降序升序,重复度,序列长度选择不同算法。
- 短序列&有序:选择插入排序
- 其它情况:快速排序最快,堆排序差距不大比较稳定
2、Pattern defeating quicksort
一种不稳定的混合排序算法。 用于C++BOOST,GO,RUST中,性能不错,实现了一个比标准库 API 在几乎所有情况下快 2x~60x 的算法库。
pivot的选择:partial insertion sort
- first:简单但效果不好,性能差
- middle:遍历数组得出中位数,遍历代价高,需要与优化性能做个trade off
- 近似中位数:短序列(小于等于8,固定元素),中序列(小于等于50,采三个元素),长序列(大于50,采九个元素)
以上是V1,V2的优化。V3针对元素重复的优化:
当pivot重复时:(partitionEqual)
- 当检测到此时的pivot和上次相同时, 使用partitionEqual将重复元素排列在一起,减少重复元素对于pivot采样的干扰。
- 当pivot选择策略不佳时,选择随机交换,避免极端情况或黑客攻击
Go 1.19版本:
优化之后的时间复杂度:
3、高性能的排序算法
根据不同情况选择不同算法, 取长补短。
理论上的算法注重理论性能,如时间、空间复杂度,生产中的算法注重场景,强调实践性能。
Go不同版本一直也是混合排序,主体是快排。Go、Rust、C ++ 的默认 unstable 排序算法虽然名义上叫快速排序(quicksort),但其实质是混合排序算法(hybrid sorting algorithm),它们虽然在大部分情况下会使用快速排序算法,但是也会在不同情况下切换到其他排序算法。只是不同的fallback时机,pivot选择策略,针对不同数据pattern采取的策略有差别。