排序算法的利弊分析及在工程中的使用| 青训营笔记

143 阅读3分钟

排序算法的利弊分析及在工程中的使用| 青训营笔记

这是我参与「第四届青训营」笔记创作活动的第3篇笔记

引入

Redis-zset,skiplist整体有序

Redis集群,主从算法、分片算法,避免单机压力过大

保证集群原信息的稳定,使用一致性算法

缓存算法LRU降低Redis压力,不需要频繁读取数据

最快的排序算法?

分情况:可并发吗?数据多少?

分语言:py-timsort C++-introsort Rust-pdqsort

问题

GO1.19的排序算法?

工程算法和课程算法的区别?

GO的排序算法是快排吗?

经典排序算法

插入排序

整理扑克牌,找到第一个比其小的元素

best O(n)

avg O(n^2)

worst O(n^2)

缺点:慢

快速排序

分治思想,不断分割直至整体有序

选定一个轴点,使用轴点分割成比轴点大/小的两个序列

best O(nlogn)

avg O(nlogn)

worst O(n^2)

堆排序

构造一个大根堆(用数组模拟)

层序遍历的结尾和根节点交换,剩余节点重新调整为大根堆,重复操作

最后得到层序遍历有序的树

best O(nlogn)

avg O(nlogn)

worst O(nlogn)

“众生平等”

元素排列情况

随机random

有序sorted/reverse

元素重复度较高mod8

根据序列长度的划分(16/128/1024)

短序列,插入排序最快

中序列、长序列,快速排序最快

序列有序时

插入排序最快

堆排序其次

快排最慢

pdsort

pattern-defeating-quicksort,一种不稳定的混合排序算法,广泛应用在C++、Rust、GO

v1

短序列使用插入排序

其他情况使用快排

当快排表现不佳时,使用堆排序维持O(nlogn)

Q:

1.短序列指多长?

12-32

2.如何知道快排表现不佳,以及如何切换堆排序?

当最终轴点的位置离序列两端很接近时(距离小于len/8)判定为表现不佳,当这种情况次数达到limit(即bits.Len(length))时,切换到堆排序。

V2

优化快排选择轴点的策略

1.使用首个元素

2.遍历寻找中位数

3.寻找近似的中位数 ✅

根据序列长度,选择决定策略

短序列(<=8),选择固定元素

中序列(<=50),采样三个元素

长序列(>50),采样九个元素

采样使得我们探知当前状态的能力

采样的元素都是逆序->序列可能已经逆序->反转整个序列

采样的元素都是顺序->序列可能已经有序->使用插入排序

ps:插入排序实际使用partial Insertion Sort

V3

还可以优化…?

短序列 插入排序 check

极端情况 堆排序 check

完全随机 选择轴点的策略 check

有序/逆序 翻转或插入排序 check

元素重复度较高mod8 ❌

采样轴点时检测重复度?采样数量有限,改进为...

如果两次partition找到相同的轴点,则认为轴点是重复元素,先将重复元素排列在一起

当上一次轴点选择策略表现不佳时(比如轴点离两端太近),随机交换元素,以防黑客攻击,limit - 1,limit = 0时调用堆排序。

\