Golang 设计实现排序算法工具包 go-sort
本次内容标题虽然包含了排序算法,但是我会更注重于工具包的设计与实现。排序算法我只实现了 冒泡排序
、选择排序
、快速排序
和 堆排序
。
工具包的设计我们需要注重于开放API的设计上,API的灵活性能直接说明工具包设计的好坏。
首先排序我们是在slice数据结构上执行的,我们应当能支持所有数据类型的slice,这就要求我们能做到不查看slice内部数据的情况下正确排序。为了做到这一点我首先定义了 Sortable
(可排序)Interface,所有实现了这些接口的类型都可以被排序:
type Sortable interface {
Len() int
Less(i, j int) bool
Swap(i, j int)
}
- Len:返回slice长度
- Less:判断第一个下标的值是否小于第二个下标的值
- Swap:两个下标的值互相交换
但是如果每一种数据结构的排序,我们都需要实现该接口的三种方法不是很方便,为了进一步提高灵活性,我定义了另一个interface Comparable
,其是针对slice内部元素的:
type Comparable interface {
LessThan(other Comparable) bool
}
- LessThan:比较两个Comparable元素,判断当前的元素是否小于给定的元素
这样我就可以定义新的一种类型:
type Slice []Comparable
即 gosort.Slice
,是我们工具包内自定义的Slice类型,我们在手动为该类型实现 Sortable
接口的所有方法:
type Slice []Comparable
func (c Slice) Len() int {
return len(c)
}
func (c Slice) Less(i, j int) bool {
return c[i].LessThan(c[j])
}
func (c Slice) Swap(i, j int) {
c[i], c[j] = c[j], c[i]
}
这下定义我们工具包内可排序的列表就非常简单了:
// 定义我们的自定义元素
type Person struct {
Age int
}
// 实现Comparable接口
func (p Person) LessThan(other gosort.Comparable) bool {
// 这里需要转换类型
person, ok := other.(Person)
if !ok {
return false
}
return p.Age < person.Age
}
// 最后定义slice即可,可以使用go原生slice的所有方法
var people gosort.Slice
people = append(people, Person{
Age: 10})
但是到这里你会发现,你只能为你自己定义的类型实现gosort.Slice,并不能为go原生的类型做这些操作。所以在这个基础上我们可以继续定义一些常用的slice类型:gosort.IntSlice
,gosort.Float64Slice
等,这里展示 gosort.IntSlice
作为例子:
type IntSlice []int
func (slice IntSlice) Len() int {
return len(slice)
}
func (slice IntSlice) Less(i, j int) bool {
return