go语言中的排序
背景
单看一些较旧的文档,go只能做一些简单的排序.
如今的go已经
- 区分稳定排序与不稳定排序
- 针对slice类型,优化代码行数
- 支持多键排序
介绍
go的sort包负责对数据的排序,主要功能
- 实现对内置类型的快捷排序
- sort.Ints()
- sort.Float64s()
- 实现对自定义类型的排序
- 实现多键排序
- 倒序排序
TODO 排序的算法
sort包支持3种算法
- 快速排序
- 插入排序
- 堆排序
简单举例
3个内置类型的slice有快捷方式
- int
- float64
- string
1 | a := [3]int{3, 1, 2} |
实现方式
核心在于 Sort
方法的参数要求实现3个函数
- Len
- Less
- Swap
1 | type IntSlice []int // 内部将[]int称为IntSlice |
故意找麻烦,使用起来如下
1 | aa := sort.IntSlice([]int{5, 2, 2, 1}) |
自定义类型排序
实现Interface接口即可
1 | type student struct { |
针对slice的排序
由于Len和Swap对于slice都很简单,
只需要提供一个闭包,表示Less函数即可.
1 | func main() { |
降序
1 | // 用 sort.Reverse包裹符合Interface接口的数据即可 |
查找
由于内部使用二分查找,因此要求
- 不能使用等于作为判断条件,必须使用不等式
- 查找升序序列,应当使用
>=
- 查找降序序列,应当使用
<=
包默认提供的 sort.SearchInts()
等方法默认序列是升序的.
1 | func main() { |
按键排序
时常遇到,时刻1需要按a键排序,时刻2需要按b键排序.
朴素法
1 | type person struct { |
画蛇添足法
1 | type By func(i, j int) bool |
绕远路法
1 | type By func(p1, p2 *person) bool |
换汤不换药法
1 | type persons []person |
多键排序
时常有按照多个键来排序的需求
两次stable排序
缺点:
- 优先级更高的应该放在后面排序,有点不习惯
- 可能有性能浪费?
1 | type person struct { |
条件表达式
缺点
- 三个条件以上就回调地狱
1 | func main() { |
将条件表达式中多个元素for循环化
核心在于如果能回答,则立即回答,
如果相同,需要下一条规则
1 | less := func(i, j int) bool { |
比如选性价比旗舰
1 | type phone struct { |
上面有一些缺点:
- 需要手动实现总less的封装
- 准备数据阶段做了实质上的倒序(比如价格指数,低者指数高),不够灵活
1 | type phone struct { |