Go标准库sort:排序

Interface 接口(你没看错,就叫Interface)

该接口是sort包的核心接口,sort包通过该接口进行排序

type Interface interface {
   Len() int // 返回元素个数
   Less(i, j int) bool // 比较
   Swap(i, j int) // 交换
}
复制代码

排序

Ints()、Float64s()、Strings()

这几个方法使用实现了对应类型的Interface接口的类对slice进行包装,这样我们就不需要自己实现Interface接口了。

package main

import (
   "fmt"
   "sort"
)

func main() {
   arr := []int{1, 3, 5, 3, 4, 2, 1, 2, 3, 6, 8, 3}
   sort.Ints(arr)
   fmt.Println(arr) // [1 1 2 2 3 3 3 3 4 5 6 8]
}
复制代码

Sort()

这个方法需要实现了Interface接口的参数,因此我们需要自己实现Interface接口,比如:

package main

import (
   "fmt"
   "sort"
)

type IntSlice []int

func (x IntSlice) Len() int           { return len(x) }
func (x IntSlice) Less(i, j int) bool { return x[i] < x[j] }
func (x IntSlice) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }

func main() {
   arr := IntSlice{1, 3, 5, 3, 4, 2, 1, 2, 3, 6, 8, 3}
   sort.Sort(arr)
   fmt.Println(arr) // [1 1 2 2 3 3 3 3 4 5 6 8]
}
复制代码

Slice()

这个方法可以只实现Interface接口的Less()方法,第一个参数是slice类型:

package main

import (
   "fmt"
   "sort"
)

func main() {
   arr := []int{1, 3, 5, 3, 4, 2, 1, 2, 3, 6, 8, 3}
   sort.Slice(arr, func(i, j int) bool {
      return arr[i] < arr[j]
   })
   fmt.Println(arr) // [1 1 2 2 3 3 3 3 4 5 6 8]
}
复制代码

Reverse()

反转,比如:

package main

import (
   "fmt"
   "sort"
)

type IntSlice []int

func (x IntSlice) Len() int           { return len(x) }
func (x IntSlice) Less(i, j int) bool { return x[i] < x[j] }
func (x IntSlice) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }

func main() {
   arr := IntSlice{1, 3, 5, 3, 4, 2, 1, 2, 3, 6, 8, 3}
   sort.Sort(arr)
   fmt.Println(arr) // [1 1 2 2 3 3 3 3 4 5 6 8]
   sort.Sort(sort.Reverse(arr))
   fmt.Println(arr) // [8 6 5 4 3 3 3 3 2 2 1 1]
}
复制代码

内部实现就算把Less()的ij换一下位置:

type reverse struct {
   Interface
}

func (r reverse) Less(i, j int) bool {
   return r.Interface.Less(j, i)
}

func Reverse(data Interface) Interface {
   return &reverse{data}
}
复制代码

Stable()、SliceStable()

保证排序是稳定的,也就是相同值得元素的原始位置不会改变:

package main

import (
   "fmt"
   "sort"
)

type Item struct {
   Index int
   Value int
}

func main() {
   arr := []Item{{1, 1}, {2, 3}, {3, 5}, {4, 3}, {5, 4}, {6, 1}, {7, 1}, {8, 1}}
   fmt.Println(arr) // [{1 1} {2 3} {3 5} {4 3} {5 4} {6 1} {7 1} {8 1}]
   arrCopy := make([]Item, len(arr))
   copy(arrCopy, arr)

   // 不稳定排序
   sort.Slice(arr, func(i, j int) bool {
      return arr[i].Value < arr[j].Value
   })
   // 本来在后边的[8 1]跑到了[6 1] [7 1]前面,[4 3]跑到了[2 3]前面
   fmt.Println(arr) // [{1 1} {8 1} {6 1} {7 1} {4 3} {2 3} {5 4} {3 5}] 

   // 稳定排序
   sort.SliceStable(arrCopy, func(i, j int) bool {
      return arrCopy[i].Value < arrCopy[j].Value
   })
   fmt.Println(arrCopy) // [{1 1} {6 1} {7 1} {8 1} {2 3} {4 3} {5 4} {3 5}]
}
复制代码

是否已经排序

共有IntsAreSorted()、、Float64sAreSorted()、StringsAreSorted()、IsSorted()、SliceIsSorted()5个方法

前三个不需要自己实现Interface接口,IsSorted()则需要自己实现Interface()接口,SliceIsSorted()可以只实现Less()方法

package main

import (
   "fmt"
   "sort"
)

func main() {
   arr := []int{1, 3, 5, 3, 4, 2, 1, 2, 3, 6, 8, 3}
   fmt.Println(sort.IntsAreSorted(arr)) // false
   sort.Ints(arr)
   fmt.Println(sort.IntsAreSorted(arr)) // true
}
复制代码

搜索

功能是搜索已经排序好的列表某个元素应该插入的下标

共有Search()、SearchInts()、SearchFloat64s()、SearchStrings()4个方法

第一个Search()需要实现Interface接口,后面3个不需要实现Interface接口

package main

import (
   "fmt"
   "sort"
)

func main() {
   arr := []int{1, 3, 5, 3, 4, 2, 1, 2, 3, 6, 8, 3}
   sort.Ints(arr)
   fmt.Println(arr) // [1 1 2 2 3 3 3 3 4 5 6 8]
   fmt.Println(sort.SearchInts(arr, 3)) // 4
   fmt.Println(sort.SearchInts(arr, 7)) // 11
}
复制代码

猜你喜欢

转载自juejin.im/post/7039596784947036197