跳过正文

Sort

·1383 字
目录

Functions
#

Find()-查找元素
#

该方法基于二分查找,需要被查找对象是排好序的,被查找对象升序降序需要与 cmp 方法保持一致,

如查找升序[]int 切片 s 时,target 如果小于 s[i], cmp 应返回小于 0 的值,相等时返回 0,大于时返回大于 0 的值

返回的是第一个被符合条件的下标

func Find(n int, cmp func(int) int) (i int, found bool)

package main

import (
	"fmt"
	"sort"
	"strings"
)

func main() {
	s := "abcdefg"
	target := "c"
	FindChar(s, target)

	s2 := []int{1, 2, 3, 4, 5}
	FindInIntSlice(s2, 3)

}

func FindChar(s, target string) {
	i, found := sort.Find(len(s), func(i int) int {
		return strings.Compare(target, string(s[i]))
	})

	if found {
		fmt.Printf("found %s in %s at %d\n", target, s, i)
	} else {
		fmt.Printf("not found %s in %s\n", target, s)
	}
}

func FindInIntSlice(s []int, target int) {
	i, found := sort.Find(len(s), func(i int) int {
		if target < s[i] {
			return -1
		} else if target == s[i] {
			return 0
		} else {
			return 1
		}
	})

	if found {
		fmt.Printf("found %d in %v at %d\n", target, s, i)
	} else {
		fmt.Printf("not found %d in %v\n", target, s)
	}
}

Float64s()-升序排序
#

对 float64 切片进行升序排序

func Float64s(x []float64)

package main

import (
    "fmt"
    "sort"
)

func main() {
    x := []float64{3, 2, 1}
    sort.Float64s(x)
    fmt.Println(x) // [1 2 3]
}

Float64AreSorted()-是否为升序排序
#

func Float64AreSorted(x []float64) bool

Ints-int 切片升序排序
#

func Ints(x []int)

IntsAreSorted()-是否为升序排序
#

func IntsAreSorted(x []int) bool

IsSorted()
#

func IsSorted(data Interface) bool

package main

import (
	"fmt"
	"sort"
)

// Test须实现sort.Interface类型方法
type Test struct {
	Data []int
}

func (t Test) Len() int {
	return len(t.Data)
}

func (t Test) Less(i, j int) bool {
	return t.Data[i] < t.Data[j]
}

func (t Test) Swap(i, j int) {
	t.Data[i], t.Data[j] = t.Data[j], t.Data[i]
}

func main() {
	x := Test{Data: []int{1, 2, 3}}
	x2 := Test{Data: []int{3, 2, 1}}
	x3 := Test{Data: []int{1, 3, 2}}

	fmt.Println(sort.IsSorted(x))  // true
	fmt.Println(sort.IsSorted(x2)) // false
	fmt.Println(sort.IsSorted(x3)) // false
}

注意:大多数场景下,slices.IsSortedFunc()(Go1.21 新增 slices 包)方法比该方法更有效,运行更快

Search()-查询元素
#

该方法也是基于二分查找,需要被查找对象是排序的

返回最小的下标,未查找到则返回-1

func Search(n int, f func(int) bool) int

package main

import (
    "fmt"
    "sort"
)

func main() {
    x := []int{1,2,3}
    target := 2
    index := sort.Search(len(x), func(i int) bool {
        return target <= x[i]
    })

    fmt.Println(index)
}

SearchFloat64s()
#

被查找对象必须升序排序

若存在,则返回最小的下标

如果 x 不存在,则返回 x 可以插入的下标位置(有可能为 len(a)),不理解为什么这么做

func SearchFloat64s(a []float64, x float64) int

package main

import (
    "fmt"
    "sort"
)

func main() {
    a := []float64{1.0, 2.0, 2.0, 3.0}
    x := 2.0

    i := sort.SearchFloat64s(a, x)
    fmt.Println(i) // 1

    x = 1.5
    i = sort.SearchFloat64s(a, x)
    fmt.Println(i) // 1, 未找到,可以插入下标1位置

    x = 4.0
    i = sort.SearchFloat64s(a, x)
    fmt.Println(i) // 4,未找到,可以插入下标4位置
}

SearchInts()
#

使用方式同 SearchFloat64s()方法

func SearchInts(a []int, x int) int

SearchStrings()
#

使用方式同 SearchFloat64s()方法

func SearchStrings(a []string, x string) int

Slice()-切片自定义排序
#

该方法无法保证元素值相同时保持原来顺序,稳定排序可以使用 SliceStable()方法

通过修改 less 方法控制是升序排序还是降序排序

func Slice(x any, less func(i, j int) bool)

package main

import (
    "fmt"
    "sort"
)

func main() {
    x := []int{1,3,2,5,4}
    sort.Slice(x, func(i, j int) bool{
        return x[i] < x[j]
    })

    fmt.Println(x)
}

SliceIsSorted()
#

SliceIsSorted(x any, less func(i, j int) bool) bool

SliceStable()-切片自定义排序:star:
#

func SliceStable(x any, less func(i, j int) bool)

package main

import (
    "fmt"
    "sort"
)

func main() {
    x := []int{1,3,2,5,4}
    sort.Slice(x, func(i, j int) bool{
        return x[i] < x[j]
    })

    fmt.Println(x)
}

Sort()
#

func Sort(data Interface)

package main

import (
	"fmt"
	"sort"
)

// Test须实现sort.Interface类型方法
type Test []int

func (t Test) Len() int {
	return len(t)
}

func (t Test) Less(i, j int) bool {
	return t[i] < t[j]
}

func (t Test) Swap(i, j int) {
	t[i], t[j] = t[j], t[i]
}

func main() {
	x := Test{4, 2, 3}

	sort.Sort(x)
	fmt.Println(x)
}

还是 sort.Slice()方法更方便一些

Stable():star:
#

使用方式同 Sort 方法

func Stable(data Interface)

Strings()
#

string 切片升序排序,建议使用 slices.Sort()方法

func Strings(x []string)

StringsAreSorted()
#

func StringsAreSorted(x []string) bool

Types
#

Interface
#

type Interface interface {
	// Len is the number of elements in the collection.
	Len() int

	// Less reports whether the element with index i
	// must sort before the element with index j.
	//
	// If both Less(i, j) and Less(j, i) are false,
	// then the elements at index i and j are considered equal.
	// Sort may place equal elements in any order in the final result,
	// while Stable preserves the original input order of equal elements.
	//
	// Less must describe a transitive ordering:
	//  - if both Less(i, j) and Less(j, k) are true, then Less(i, k) must be true as well.
	//  - if both Less(i, j) and Less(j, k) are false, then Less(i, k) must be false as well.
	//
	// Note that floating-point comparison (the < operator on float32 or float64 values)
	// is not a transitive ordering when not-a-number (NaN) values are involved.
	// See Float64Slice.Less for a correct implementation for floating-point values.
	Less(i, j int) bool

	// Swap swaps the elements with indexes i and j.
	Swap(i, j int)
}