这是我参与「第三届青训营 -后端场」笔记创作活动的第2篇笔记
一、经典排序算法
1、插入排序
-
基本思想 插入排序是一种最简单的排序方法,它的基本思想是在待排序的元素中,假设前面
n-1(其中n>=2)个数已经是排好顺序的,现将第n个数插到前面已经排好的序列中,然后找到合适自己的位置,使得插入第n个数的这个序列也是排好顺序的。按照此法对所有元素进行插入,直到整个序列排为有序为止。 -
过程(升序)
value 3 2 5 1 index 0 1 2 3 - ①
index=1与index=0两者比较,前者大于后者时,index=1的值插入到index=0前面,这时序列的前两者已经排好,进入下一步; - ②
index=2与index=1两者比较,前者大于后者,index=2的值插入到index=1前面,重复①,进入下一步; - ③
index=3与index=2两者比较,前者大于后者,index=3的值插入到index=2前面,重复②,结束。这时,序列已排好序。
- ①
-
Go实现
2、快速排序
-
基本思想 首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它左边,所有比它大的数都放到它右边。利用分治的思想,左右两边分开独立完成上述排序,递归或迭代重复这个过程即可。
-
Go实现
3、堆排序
-
基本思想 在堆的数据结构中,堆中的最大值总是位于根节点(在优先队列中使用堆的话堆中的最小值位于根节点)。堆中定义以下几种操作:
- 最大堆调整):将堆的末端子节点作调整,使得子节点永远小于父节点
- 创建最大堆:将堆中的所有数据重新排序
- 排序:移除位在第一个数据的根节点,并做最大堆调整的递归运算
-
Go实现
4、三种算法对比
-
时间复杂度对比
best avg worst insert O(n) O(n^2) O(n^2) quick O(n * logn) O(n * logn) O(n^2) heap O(n * logn) O(n * logn) O(n * logn)
二、bdpsort
1、简介
- 不稳定的混合排序算法
- 对常见序列类型做了特殊化的优化,在不同的条件下都拥有不错的性能
- “不断判定目前的序列情况,然后使用不同的方式和路径达到最优解”
2、version1
个人理解是类似于在快速排序分区后得到pivot再进行算法的选择,序列长度小于24,直接插入排序得到结果;在分区时得到的pivot在序列两端的次数到达limit次,则使用堆排序保持O(n * logn)的性能,其余情况都需要再分区。
-
实现 尝试把上述的
quickSort修改成下面的样子,貌似能实现。
3、version2
version1中pivot选取为序列的首个数据,这种选取策略是最简单的,但是很容易产生下图的情况:pivot过于接近序列两端。
因此,进一步的优化可以从pivot的选择入手。当pivot选取为整个序列的中位数或近似中位数,这是最好的情况。
4、final version
version2的进一步优化:对pivot重复的情况进行优化,将重复的pivot放在一起,减少快排表现不佳的情况。
-
final 版本的时间复杂度:
best avg worst O(n) O(n * logn) O(n * logn)
参考资料