数据结构与算法 | 青训营笔记

151 阅读2分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第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),采样九个元素

采样过程中我们可以探知当前序列的状态:

若采样元素都是逆序,有可能序列已经是逆序,反转序列。

若采样元素都是顺序,有可能序列已经是有序,使用插入排序。

没有完美的排序算法,一般情况下都是使用混合排序算法。