这是我参与「第三届青训营 -后端场」笔记创作活动的的第四篇笔记
为什么要学习数据结构和算法?
由于项目需求,需要使用Redis数据库,为了保证Redis集群的稳定,需要使用到一些算法。因 此在后端使用某些算法可以降低Redis的压力,所以就需要数据结构和算法。
总结:数据结构和算法几乎在于程序开发中的所有地方。
经典的排序算法
不同场景下需要用不同的排序算法才能达到最好的效果,因此没有排序算法可以说是最快最好的。
- 插入排序:从第二个元素开始与前驱元素进行一一对比,比较结果决定是否移动位置。最好的情况是有序排列的数组,时间复杂度为O(n),最差为O(n^2)。
- 快速排序:将数组递归分开,用两个指针,分别指向左右两边,一次比较大小,交替进行,时间复杂度最好和最坏都为O(n^2)。性能处于中间层次
- 堆排序:利用不断地调整堆排序,使堆保持最大或最小根堆。通过上滤或下滤的操作来实现调整堆。堆排序最好最坏都为O(nlog2n)。
根据序列元素排列情况划分
- 完全随机的情况(random)
- 有序/逆序的情况(sorted/reverse)
- 元素重复度较高的情况(mod8)
在此基础上,还需要根据序列长度的划分(16/128/1024)
- 在随机的短序列中,插入排序最快,在随机的长序列和中序列中,堆排序和快速排序相差不大。但快排在长序列和中序列中速度最快。
- 在序列有序中,插入排序在三种情况下都很快,而堆排序相差10倍,快速排序相差几十倍。
- 大部分情况下,快速排序效果比较好。在任何情况下,堆排序都比较稳定。在短序列情况下,插入排序性能最好。
所以在应用中,面对短排序一般都用插入排序。如果在开发中,你的快速排序分的两个部分比较少(最终的pivot距离序列的两端很接近),这个时候使用快速排序就不太好,我们可以换位堆排序,因为堆排序在任何情况下都比较稳定。
从零开始打造 pdqsort
-
关于pivot的选择
- 使用首个元素作为pivot实现简单,但是往往效果不好
- 但是寻找中位数的方法又需要遍历数组,性能不好
-
根据序列长度的不同,来决定选择策略
- 中序列中,我们采集三种元素,寻找他的中位数。从前中后三个位置选取三种元素,选取三个元素中的中位数。
- 长序列中,我们采集九种元素,找到它们之间的中位数。
-
优化重复元素很多的情况
- 采样时pivot的数量有限,所以不一定会采样到相同的元素
- 我们可以对两次partition生成的pivot进行比对,如果两个partition生成的pivot相同,则认为此次分割无效。