sort.Interface 接口
这个接口是 sort 包的核心,它有3个方法。这是 Golang 很酷的一个特性,只要数据类型满足 sort.Interface
接口,就可以用sort包的函数进行排序。
// 一个满足sort.Interface接口的(集合)类型可以被本包的函数进行排序。
// 方法要求集合中的元素可以被整数索引。
type Interface interface {
// Len方法返回集合中的元素个数
Len() int
// Less方法报告索引i的元素是否比索引j的元素小
Less(i, j int) bool
// Swap方法交换索引i和j的两个元素
Swap(i, j int)
}
Example1
package main
import (
"fmt"
"sort"
)
//自定义一个类型
type ints []int
func (s ints) Len() int { return len(s) }
func (s ints) Less(i, j int) bool { return s[i] < s[j] }
func (s ints) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func main() {
nums := []int{9, 8, 5, 4, 7, 6, 3, 0, 1, 2}
sort.Sort(ints(nums)) //进行排序
fmt.Println(nums)
}
Output: [0 1 2 3 4 5 6 7 8 9]
Example2
package main
import (
"fmt"
"sort"
)
type Person struct {
Name string
Age int
}
type Persons []Person
func (s Persons) Len() int { return len(s) }
func (s Persons) Less(i, j int) bool { return s[i].Age < s[j].Age }
func (s Persons) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func main() {
p := []Person{Person{"Lily", 20}, Person{"Bing", 18}, Person{"Tom", 23}, Person{"Vivy", 16}, Person{"John", 18}}
sort.Sort(sort.Reverse(Persons(p))) //sort.Reverse 生成递减序列
fmt.Println(p)
}
Output: [{Tom 23} {Lily 20} {Bing 18} {John 18} {Vivy 16}]
sort 包内置的排序方法
So easy ! 看了2个例子你应该明白了吧!
方法 | 说明 |
---|---|
func Sort(data Interface) | 递增排序,不能保证排序的稳定性,即不保证相等元素的相对次序不变。用的是快速排序算法。 |
func Stable(data Interface) | 递增排序,保证排序的稳定性,相等元素的相对次序不变。用的是插入排序算法。 |
func IsSorted(data Interface) bool | 判断data是否已经被递增排序 |
func Reverse(data Interface) Interface | 对该接口排序可生成递减序列 |
func Ints(a []int) | 将 []int 排序为递增顺序 |
func IntsAreSorted(a []int) bool | 检查 []int 是否已排序为递增顺序 |
func Float64s(a []float64) | 将 []float64 排序为递增顺序 |
func Float64sAreSorted(a []float64) bool | 检查 []float64 是否已排序为递增顺序 |
func Strings(a []string) | 将 []string 排序为递增顺序 |
func StringsAreSorted(a []string) bool | 检查 []string 是否已排序为递增顺序 |
Example:
s := []int{5, 2, 6, 3, 1, 4} // unsorted
sort.Ints(s)
fmt.Println(s)
Output: [1 2 3 4 5 6]
使用自定义排序算法
package main
import (
"fmt"
"sort"
)
//bubbleSort 冒泡排序
func bubbleSort(data sort.Interface) {
r := data.Len() - 1
for i := 0; i < r; i++ {
for j := r; j > i; j-- {
if data.Less(j, j-1) {
data.Swap(j, j-1)
}
}
}
}
//insertSort 插入排序
func insertSort(data sort.Interface) {
r := data.Len() - 1
for i := 1; i <= r; i++ {
for j := i; j > 0 && data.Less(j, j-1); j-- {
data.Swap(j, j-1)
}
}
}
//selectSort 选择排序
func selectSort(data sort.Interface) {
r := data.Len() - 1
for i := 0; i < r; i++ {
min := i
for j := i + 1; j <= r; j++ {
if data.Less(j, min) {
min = j
}
}
data.Swap(i, min)
}
}
func main() {
nums := []int{9, 8, 5, 4, 7, 6, 3, 0, 1, 2}
ints := sort.IntSlice(nums) //IntSlice给[]int添加方法以满足Interface接口,以便排序为递增序列。
bubbleSort(ints) //使用冒泡排序
fmt.Println(ints)
}
output: [0 1 2 3 4 5 6 7 8 9]
搜索
搜索和排序是2兄弟,搜索是从已经排序的数据中返回数据的位置。
方法 | 说明 |
---|---|
func SearchInts(a []int, x int) int | SearchInts在递增顺序的a中搜索x,返回x的索引。如果查找不到,返回值是x应该插入a的位置(以保证a的递增顺序),返回值可以是len(a)。是Search函数函数的包装。 |
func SearchFloat64s(a []float64, x float64) int | 同上,只是数据类型不同 |
func SearchStrings(a []string, x string) int | 同上,只是数据类型不同 |
func Search(n int, f func(int) bool) int | 采用二分法搜索找到[0, n)区间内最小的满足f(i)==true的值i。返回找到的索引i,如果没有符合要求的索引,则返回 n。 |
Example1:[]int 搜索
package main
import (
"fmt"
"sort"
)
func main() {
data := sort.IntSlice{9, 5, 3, 25, 1, 5, 64, 45, 21, 48, 55}
data.Sort() // 等价于调用 sort.Sort,搜索前需要先排序。
fmt.Println(data)
x := 5
i := data.Search(x) // 等价于调用 sort.SearchInts
fmt.Printf("%v is present at data[%d]\n", x, i)
}
output:
[1 3 5 5 9 21 25 45 48 55 64]
5 is present at data[2]
Example2: []struct 搜索
package main
import (
"fmt"
"sort"
)
type Person struct {
Name string
Age int
}
type Persons []Person
func (s Persons) Len() int { return len(s) }
func (s Persons) Less(i, j int) bool { return s[i].Age < s[j].Age }
func (s Persons) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func main() {
p := []Person{Person{"Lily", 20}, Person{"Bing", 18}, Person{"Tom", 23}, Person{"Vivy", 16}, Person{"John", 18}}
sort.Sort(sort.Reverse(Persons(p))) //sort.Reverse 生成递减序列
fmt.Println(p)
x := 18
i := sort.Search(len(p), func(i int) bool {
//如果使用 p[i].Age == x,则找不到索引时返回的是n,而不是列表应该插入的位置,会破坏列表顺序。
//在升序列表中使用 p[i].Age >= x,则找不到索引时返回接近x的位置,以保证列表的递增顺序
//在降序列表中使用 p[i].Age <= x,则找不到索引时返回接近x的位置,以保证列表的递减顺序
return p[i].Age <= x
})
fmt.Println(i)
}
output:
[{Tom 23} {Lily 20} {Bing 18} {John 18} {Vivy 16}]
2