golang标准库之sort

作者: adm 分类: go 发布时间: 2023-10-01

简介
标准库sort实现了4种排序方法,插入排序、堆排序、快排和归并排序,但是并没有暴露给用户接口。sort包会根据数据选择最优的排序方法(其实只使用了3种,归并排序除外)。

接口
用户需要实现以下接口才能使用sort包的排序功能。

type Interface interface {
    // Len is the number of elements in the collection.
    Len() int
    // Less reports whether the element with
    // index i should sort before the element with index j.
    Less(i, j int) bool
    // Swap swaps the elements with indexes i and j.
    Swap(i, j int)
}
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}
}

func IsSorted(data Interface) bool { // 当前排序与Less()方法排序一致返回True
    n := data.Len()
    for i := n - 1; i > 0; i-- {
        if data.Less(i, i-1) {
            return false
        }
    }
    return true
}

内置类型支持
对于常用的类型(整型切片、float64切片、String切片),sort包提供了内置的接口实现

type IntSlice []int

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

func (p IntSlice) Sort() { Sort(p) }

type Float64Slice []float64

func (p Float64Slice) Len() int           { return len(p) }
func (p Float64Slice) Less(i, j int) bool { return p[i] < p[j] || isNaN(p[i]) && !isNaN(p[j]) }
func (p Float64Slice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

func isNaN(f float64) bool {
    return f != f
}

func (p Float64Slice) Sort() { Sort(p) }

type StringSlice []string

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

func (p StringSlice) Sort() { Sort(p) }

使用举例如下:

package main

import (
    "fmt"
    "sort"
)

func main() {
    instance := sort.IntSlice{1, 5, 8, 9, 7, 1}
    sort.Sort(instance)
    fmt.Println(instance) // [1 1 5 7 8 9]
    sort.Sort(sort.Reverse(instance))
    fmt.Println(instance) // [9 8 7 5 1 1]
}

自定义类型排序

package main

import (
    "fmt"
    "sort"
)

type Person struct {
    age  int
    name string
    sex  string
}

type PersonSlice []Person

func (p PersonSlice) Len() int {
    return len(p)
}

func (p PersonSlice) Less(i, j int) bool {
    return p[i].age < p[j].age
}

func (p PersonSlice) Swap(i, j int) {
    p[i], p[j] = p[j], p[i]
}

func (p PersonSlice) Sort() {
    sort.Sort(p)
}

func main() {
    instance := PersonSlice{{12, "Jack", "male"}, {15, "Lucy", "famale"}, {13, "Lilei", "male"}}
    instance.Sort()
    fmt.Println(instance) // [{12 Jack male} {13 Lilei male} {15 Lucy famale}]
}

其它封装函数

// Ints sorts a slice of ints in increasing order.
func Ints(a []int) { Sort(IntSlice(a)) }

// Float64s sorts a slice of float64s in increasing order
// (not-a-number values are treated as less than other values).
func Float64s(a []float64) { Sort(Float64Slice(a)) }

// Strings sorts a slice of strings in increasing order.
func Strings(a []string) { Sort(StringSlice(a)) }

// IntsAreSorted tests whether a slice of ints is sorted in increasing order.
func IntsAreSorted(a []int) bool { return IsSorted(IntSlice(a)) }

// Float64sAreSorted tests whether a slice of float64s is sorted in increasing order
// (not-a-number values are treated as less than other values).
func Float64sAreSorted(a []float64) bool { return IsSorted(Float64Slice(a)) }

// StringsAreSorted tests whether a slice of strings is sorted in increasing order.
func StringsAreSorted(a []string) bool { return IsSorted(StringSlice(a)) }

举例如下:


package main

import (
    "fmt"
    "sort"
)

func main() {
    num := []int{1, 5, 8, 9, 7, 1}
    fmt.Println(sort.IntsAreSorted(num)) // false
    sort.Ints(num)
    fmt.Println(num, sort.IntsAreSorted(num)) // [1 1 5 7 8 9] true
}

如果觉得我的文章对您有用,请随意赞赏。您的支持将鼓励我继续创作!