这是我参与「第三届青训营 -后端场」笔记创作活动的的第4篇笔记。
一、为什么要学习数据结构和算法?
在各种存储、计算过程中,都需要用到数据结构和算法进行优化,保证空间和时间的最大化利用。
什么是最快的排序算法:Python-timesort、C++ - inrosort、Rust - pdqsort
_go的排序算法:_introsort
二、经典排序算法
插入排序 | 快速排序 | 堆排序 | Benchmark
插入排序
将元素不断插入以及排序好的array中
-
起始只有一个元素,后续元素插入有序序列中并不断交换,知道找到第一个比其小的元素。
-
**缺点:**平均和最坏情况时间复杂度高达O(n^2)。
-
**优点:**最好情况时间复杂度为O(n)。
快速排序
分治思想,不断分割序列直到序列整体有序
-
选定一个轴点,使用轴点分割序列,分为比轴点大和比轴点小两个序列。
-
**缺点:**最坏情况时间复杂度高达O(n^2)。
-
**优点:**平均情况时间复杂度为O(n*logn)。
堆排序
利用堆的性质实现的排序算法
-
构造大顶堆,将根节点(最大元素)交换到最后一个位置,调整整个堆,如此反复。
-
**缺点:**最好情况时间复杂度高达O(n*logn)。
-
**优点:**最坏情况时间复杂度为O(n*logn)。
插入性能最差,快排整体平均,堆排序非常稳定。
插入排序适用场景:短序列,已有序序列
快速排序适用场景:中长序列,无序序列
堆排序适用场景:任意序列,无序序列
三、从零开始打造pdqsort
pdqsort(pattern-defeating-quicksort)
是一种不稳定的混合排序算法,对常见的序列类型做了特殊优化,使得其在不用条件下都拥有不错的性能。
具体思想:短序列适用插入排序,其他情况使用快速排序,快排表现不佳时使用堆排序保证最坏情况。
短序列长度:12~32
当最终pivot的位置里序列两端很接近时(小于length/8),当这种情况的次数达到limit(bits.Len(length)),切换到堆排序
如何进一步加速?
尽量使快排的轴点为序列的中位数。
pivot的选择
-
短序列(<=8),固定元素
-
中序列(<=50),采样三个元素
-
长序列(>50),采样九个元素
采样过程中我们可以探知当前序列的状态:
若采样元素都是逆序,有可能序列已经是逆序,反转序列。
若采样元素都是顺序,有可能序列已经是有序,使用插入排序。
没有完美的排序算法,一般情况下都是使用混合排序算法。