这是我参与「第三届青训营 -后端场」笔记创作活动的的第5篇笔记
课程简图:
例子-抖音直播排行榜功能
规则:某个时间段内,直播间礼物数TOP10房间获得奖励,需要在每个房间展示排行榜
解决方案:
- 礼物数量存储在Redis-zset中,使用skiplist使得元素整体有序
- 使用Redis集群,避免单机压力过大,使用主从算法、分片算法
- 保证集群原信息的稳定,使用一致性算法
- 后端使用缓存算法(LRU)降低Redis压力,展示房间排行榜
数据结构几乎存在于程序开发的所有地方
Go 1.19 排序算法的设计
1. Inserting Sort 插入排序
最好时间复杂度 O(n)
平均时间复杂度 O(n^2)
最坏时间复杂度 O(n^2)
缺点
- 平均和最坏情况下时间复杂度高
优点
- 最好情况下时间复杂度O(n)
2.Quick Sort 快速排序
最好时间复杂度O(n*logn)
平均时间复杂度O(n*logn)
最坏时间复杂度O(n^2)
缺点
- 最坏情况下时间复杂度O(n^2)
优点
- 平均情况下时间复杂度O(n*logn)
3.Heap Sort 堆排序
最好时间复杂度O(n*logn)
平均时间复杂度O(n*logn)
最坏时间复杂度O(n*logn)
缺点
- 最好情况下时间复杂度O(n*logn)
三个经典排序的比较:
根据序列元素排列情况划分:
- 完全随机的情况(random)
- 有序/逆序的情况(sort/reverse)
- 元素重复度较高的情况(mod8) 在此基础上,还需要根据序列长度的划分(16/128/1024)
完全随机的情况
短序列:
速度:
插排>快排>堆排
中序列:
速度:
快排>堆排>插排
长序列:
速度:
快排>堆排>插排
有序/逆序的情况(sort/reverse)
短序列:
速度:
插排>堆排>快排
中序列:
速度:
插排>堆排>快排
长序列:
速度:
插排>堆排>快排
结论
- 所有短序列和元素有序情况下,插入排序的性能最好
- 在大部分的情况下,快排有较好的总和性能
- 几乎在任何情况下,堆排的表现都比较稳定
比喻:
那么就有了一个排序算法 把这三种排序算法的优点结合起来:
pdqsort
结合三种排序方法的优点:
- 对于短序列(长度小于一定时)我们使用插入排序
- 其他情况,使用快速排序来保证整体性能
- 当快速排序表现不佳时,使用堆排序来保证最坏情况下时间复杂度仍然为O(n*logn)
流程简图:
各种优化策略:
最终流程图:
- 高性能的排序算法是根据不同情况选择不同策略,取长补短
- 理论算法注重理论性能,例如时间复杂度,空间复杂度等。生产环境中的算法需要面对不同的实践场景,更加注重实践性能
- Go 语言的排序算法一直都是混合算法,主体是快速排序,是在快排的基础上进行一些优化
本节课的笔记就到此结束了,谢谢阅读!