一. 数据结构与算法
01.为什么要学习数据结构和算法
了解课本上学习到的算法和真正在生产实践中使用的算法之间的差异
规则:某个时间段内,直播间礼物数TOP10房间获得奖励,需要在每个房间展示排行榜
解决方案:
- 礼物数量存储在Redis-zset中,使用skiplist使得元素整体有序
- 使用Redis集群,避免单机压力过大,使用主从算法、分片算法
- 保证集群原信息的稳定,使用一致性算法
- 后端使用缓存算法(LRU)降低Redis压力,展示房间排行榜
- 数据结构和算法几乎存在于程序开发中的所有地方
问题:
- Go 1.19的排序算法是如何设计的?
- 生产环境中使用的的排序算法和课本上的排序算法有什么区别?
- Go语言的排序算法是快速排序么?
02.经典排序算法
复现在课本上学习到的经典排序算法,讲解它们的原理以及特点
1. 插入排序
Insertion Sort插入排序
https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c263ec7bd9d74db3b456dd341213fd2c~tplv-k3u1fbpfcp-watermark.image
将元素不断插入已经排序好的array中
- 起始只有一个元素5,其本身是一个有序序列
- 后续元素插入有序序列中,即不断交换,直到找到第一个比其小的元素
缺点
平均和最坏情况的时间复杂度高达O(n^2)
优点
最好情况时间复杂度为O(n)
2. 快速排序
Quick Sort快速排序
分治思想,不断分割序列直到序列整体有序
- 选定一个pivot (轴点)
- 使用pivot分割序列,分成元素比pivot大和元素比pivot小两个序列
缺点
最坏情况的时间复杂度高达O(n^2)
优点
平均情况的时间复杂度为O(n*logn)
3. 堆排序
Heap Sort堆排序
利用堆的性质形成的排序算法
- 构造一个大顶堆
- 将根节点(最大元素)交换到最后一个位置,调整整个堆,如此反复
https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e15100a8c74b47efb07961167647e159~tplv-k3u1fbpfcp-watermark.image
缺点
最好情况的时间复杂度高达O(n*logn)
优点
最坏情况的时间复杂度为O(n*logn)
二. 经典算法理论印象
-
插入排序平均和最坏情况时间复杂度都是O(n^2),性能不好
-
快速排序整体性能处于中间层次
-
堆排序性能稳定,“众生平等”
三. 实际场景benchmark
3.1根据序列元素排列情况划分
- 完全随机的情况(random)
- 有序/逆序的情况(sorted/reverse)
- 元素重复度较高的情况(mod8) 在此基础上,还需要根据序列长度的划分(16/128/1024)
3.2Benchmark - random
- 插入排序在短序列中速度最快
- 快速排序在其他情况中速度最快
- 堆排序速度于最快算法差距不大
3.3Benchmark -sorted
插入排序在序列已经有序的情况下最快
3.4实际场景benchmark结论
- 所有短序列和元素有序情况下,插入排序性能最好
- 在大部分的情况下,快速排序有较好的综合性能
- 几乎在任何情况下,堆排序的表现都比较稳定
插入排序 ->单车
快速排序->汽车
堆排序->地铁
03.从零开始打造pdqsort
从零开始打造目前业界性能一流的排序 算法pdqsort (Pattern--Defeating--QuickSort)
四.个人感悟
- 学好基础的数据结构很重要
- 多复习,多敲代码