《Go语言四十二章经》第二十九章 排序(sort)

    Go语言标准库sort包中实现了3种基本的排序算法:插入排序、快排和堆排序。和其他语言中一样,这三种方式都是不公开的,他们只在sort包内部使用。所以用户在使用sort包进行排序时无需考虑使用那种排序方式,sort.Interface定义的三个方法:获取数据集合长度的Len()方法、比较两个元素大小的Less()方法和交换两个元素位置的Swap()方法,就可以顺利对数据集合进行排序。sort包会根据实际数据自动选择高效的排序算法。

    任何实现了 sort.Interface 的类型(一般为集合),均可使用该包中的方法进行排序。这些方法要求集合内列出元素的索引为整数。

    1. import (
    2. "fmt"
    3. "sort"
    4. )
    5. func main() {
    6. a := []int{3, 5, 4, -1, 9, 11, -14}
    7. sort.Ints(a)
    8. fmt.Println(a)
    9. ss := []string{"surface", "ipad", "mac pro", "mac air", "think pad", "idea pad"}
    10. sort.Strings(ss)
    11. fmt.Println(ss)
    12. sort.Sort(sort.Reverse(sort.StringSlice(ss)))
    13. fmt.Printf("After reverse: %v\n", ss)
    14. }
    1. 程序输出:
    2. [-14 -1 3 4 5 9 11]
    3. [idea pad ipad mac air mac pro surface think pad]
    4. After reverse: [think pad surface mac pro mac air ipad idea pad]
    1. 程序输出:
    2. After reversed: [9 8 7 6 5 4 3 2 1]

    相关方法:

    1. // 将类型为float64的slice以升序方式排序
    2. func Float64s(a []float64)
    3. // 判定是否已经进行排序func Ints(a []int)
    4. func Float64sAreSorted(a []float64) bool 
    5. // Ints 以升序排列 int 切片。
    6. func Ints(a []int)
    7. // 判断 int 切片是否已经按升序排列。
    8. func IntsAreSorted(a []int) bool 
    9. func IsSorted(data Interface) bool
    10. //Strings 以升序排列 string 切片。
    11. func Strings(a []string)
    12. //判断 string 切片是否按升序排列
    13. func StringsAreSorted(a []string) bool
    14. // search使用二分法进行查找,Search()方法回使用“二分查找”算法来搜索某指定切片[0:n],
    15. // 并返回能够使f(i)=true的最小的i(0<=i<n)值,并且会假定,如果f(i)=true,则f(i+1)=true,
    16. // 即对于切片[0:n],i之前的切片元素会使f()函数返回false,i及i之后的元素会使f()
    17. // 函数返回true。但是,当在切片中无法找到时f(i)=true的i时(此时切片元素都不能使f()
    18. // 函数返回true),Search()方法会返回n(而不是返回-1)。
    19. //
    20. // Search 常用于在一个已排序的,可索引的数据结构中寻找索引为 i 的值 x,例如数组或切片。
    21. // 这种情况下实参 f一般是一个闭包,会捕获所要搜索的值,以及索引并排序该数据结构的方式。
    22. func Search(n int, f func(int) bool) int
    23. // SearchFloat64s 在float64s切片中搜索x并返回索引如Search函数所述.
    24. // 返回可以插入x值的索引位置,如果x不存在,返回数组a的长度切片必须以升序排列
    25. func SearchFloat64s(a []float64, x float64) int  
    26. // SearchInts 在ints切片中搜索x并返回索引如Search函数所述. 返回可以插入x值的
    27. // 索引位置,如果x不存在,返回数组a的长度切片必须以升序排列
    28. func SearchInts(a []int, x int) int
    29. // SearchFloat64s 在strings切片中搜索x并返回索引如Search函数所述. 返回可以
    30. // 插入x值的索引位置,如果x不存在,返回数组a的长度切片必须以升序排列
    31. func SearchStrings(a []string, x string) int
    32. // 其中需要注意的是,以上三种search查找方法,其对应的slice必须按照升序进行排序,
    33. // 否则会出现奇怪的结果.
    34. // Sort 对 data 进行排序。它调用一次 data.Len 来决定排序的长度 n,调用 data.Less
    35. // 和 data.Swap 的开销为O(n*log(n))。此排序为不稳定排序。他根据不同形式决定使用
    36. // 不同的排序方式(插入排序,堆排序,快排)。
    37. func Sort(data Interface)
    38. // Stable对data进行排序,不过排序过程中,如果data中存在相等的元素,则他们原来的
    39. // 则利用Stable对data进行排序后,i依然小于j.直接利用sort进行排序则不能够保证这一点。
    40. func Stable(data Interface)
    1. 程序输出:
    2. Sort: [{CCC 0} {EEE 11} {BBB 22} {DDD 22} {AAA 55}]
    3. Stable: [{CCC 0} {EEE 11} {BBB 22} {DDD 22} {AAA 55}]

    利用sort.Slice 函数,而不用提供一个特定的 sort.Interface 的实现,而是 Less(i,j int) 作为一个比较回调函数,可以简单地传递给 sort.Slice 进行排序。

    1. package main
    2. import (
    3. "fmt"
    4. "sort"
    5. )
    6. type Peak struct {
    7. Name string
    8. Elevation int // in feet
    9. }
    10. func main() {
    11. peaks := []Peak{
    12. {"Aconcagua", 22838},
    13. {"Denali", 20322},
    14. {"Kilimanjaro", 19341},
    15. {"Mount Elbrus", 18510},
    16. {"Mount Everest", 29029},
    17. {"Mount Kosciuszko", 7310},
    18. {"Mount Vinson", 16050},
    19. {"Puncak Jaya", 16024},
    20. }
    21. // does an in-place sort on the peaks slice, with tallest peak first
    22. sort.Slice(peaks, func(i, j int) bool {
    23. return peaks[i].Elevation >= peaks[j].Elevation
    24. })
    25. fmt.Println(peaks)