Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

sort 包详解

概述

sort 包提供了对切片和用户定义集合进行排序的原语。

核心功能

  • 基本类型切片排序(int、float64、string)
  • 自定义类型排序(实现 Interface 接口)
  • 使用比较函数排序(Slice、SliceStable)
  • 检查切片是否已排序
  • 二分查找功能
  • 稳定排序支持

重要说明

  • Go 版本:所有 Go 版本都支持
  • 排序算法:使用 pdqsort(模式防御快速排序)
  • 时间复杂度:最坏情况 O(n log n)
  • ⚠️ 稳定性:Sort 不稳定,Stable 稳定

包导入

import "sort"

接口和类型

Interface

type Interface interface {
    Len() int
    Less(i, j int) bool
    Swap(i, j int)
}

功能: 任何实现了这三个方法的类型都可以使用 sort 包进行排序。

方法说明

  • Len() int - 集合中元素的数量
  • Less(i, j int) bool - 索引 i 的元素是否应该排在索引 j 的元素之前
  • Swap(i, j int) - 交换索引 i 和 j 的元素

示例

package main

import (
    "fmt"
    "sort"
)

type Person struct {
    Name string
    Age  int
}

// ByAge 实现 sort.Interface
type ByAge []Person

func (a ByAge) Len() int           { return len(a) }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
func (a ByAge) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }

func main() {
    people := []Person{
        {"Alice", 23},
        {"Bob", 25},
        {"Charlie", 20},
    }
    
    sort.Sort(ByAge(people))
    fmt.Println(people)
    // [{Charlie 20} {Alice 23} {Bob 25}]
}

IntSlice

type IntSlice []int

功能: 实现了 sort.Interface 的 int 切片类型。

方法

  • Len() int
  • Less(i, j int) bool - x[i] < x[j]
  • Swap(i, j int)
  • Sort() - 对切片排序
  • Search(x int) int - 二分查找

示例

package main

import (
    "fmt"
    "sort"
)

func main() {
    nums := sort.IntSlice{5, 2, 8, 1, 9}
    
    nums.Sort()
    fmt.Println(nums) // [1 2 5 8 9]
    
    // 查找元素
    idx := nums.Search(8)
    fmt.Printf("8 在索引 %d\n", idx) // 8 在索引 3
}

Float64Slice

type Float64Slice []float64

功能: 实现了 sort.Interface 的 float64 切片类型。

注意

  • NaN 值会被排到最后
  • Less 方法:x[i] < x[j] || (isNaN(x[i]) && !isNaN(x[j]))

方法

  • Len() int
  • Less(i, j int) bool
  • Swap(i, j int)
  • Sort()
  • Search(x float64) int

示例

package main

import (
    "fmt"
    "math"
    "sort"
)

func main() {
    nums := sort.Float64Slice{3.14, 1.59, math.NaN(), 2.65}
    
    nums.Sort()
    fmt.Println(nums) // [1.59 2.65 3.14 NaN]
}

StringSlice

type StringSlice []string

功能: 实现了 sort.Interface 的 string 切片类型。

方法

  • Len() int
  • Less(i, j int) bool - x[i] < x[j]
  • Swap(i, j int)
  • Sort()
  • Search(x string) int

示例

package main

import (
    "fmt"
    "sort"
)

func main() {
    names := sort.StringSlice{"Charlie", "Alice", "Bob"}
    
    names.Sort()
    fmt.Println(names) // [Alice Bob Charlie]
    
    // 查找元素
    idx := names.Search("Bob")
    fmt.Printf("Bob 在索引 %d\n", idx) // Bob 在索引 1
}

函数详解(按 A-Z 分类)

F

Find

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

功能: 使用二分查找找到并返回最小的索引 i,使得 cmp(i) <= 0

参数

  • n int - 搜索范围 [0, n)
  • cmp func(int) int - 比较函数
    • 返回值 > 0:目标小于当前元素
    • 返回值 = 0:目标等于当前元素
    • 返回值 < 0:目标大于当前元素

返回值

  • i int - 找到的索引,如果不存在返回 n
  • found bool - 是否找到

要求

  • cmp(i) > 0 在前缀
  • cmp(i) == 0 在中间
  • cmp(i) < 0 在后缀

示例

package main

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

func main() {
    names := []string{"Alice", "Bob", "Charlie", "David"}
    target := "Charlie"
    
    idx, found := sort.Find(len(names), func(i int) int {
        return strings.Compare(target, names[i])
    })
    
    if found {
        fmt.Printf("找到 %s 在索引 %d\n", target, idx)
    } else {
        fmt.Printf("%s 未找到,应插入索引 %d\n", target, idx)
    }
}

运行结果

找到 Charlie 在索引 2

F

Float64s

func Float64s(x []float64)

功能: 对 float64 切片进行升序排序。

参数

  • x []float64 - 要排序的切片

注意

  • 原地排序
  • NaN 排在最后

示例

package main

import (
    "fmt"
    "sort"
)

func main() {
    nums := []float64{3.14, 1.59, 2.65, 3.58}
    sort.Float64s(nums)
    fmt.Println(nums) // [1.59 2.65 3.14 3.58]
}

Float64sAreSorted

func Float64sAreSorted(x []float64) bool

功能: 检查 float64 切片是否已按升序排序。

参数

  • x []float64 - 要检查的切片

返回值

  • bool - 是否已排序

示例

package main

import (
    "fmt"
    "sort"
)

func main() {
    nums1 := []float64{1.59, 2.65, 3.14, 3.58}
    nums2 := []float64{3.14, 1.59, 2.65}
    
    fmt.Println(sort.Float64sAreSorted(nums1)) // true
    fmt.Println(sort.Float64sAreSorted(nums2)) // false
}

I

Ints

func Ints(x []int)

功能: 对 int 切片进行升序排序。

参数

  • x []int - 要排序的切片

注意

  • 原地排序

示例

package main

import (
    "fmt"
    "sort"
)

func main() {
    nums := []int{5, 2, 8, 1, 9, 3}
    sort.Ints(nums)
    fmt.Println(nums) // [1 2 3 5 8 9]
}

IntsAreSorted

func IntsAreSorted(x []int) bool

功能: 检查 int 切片是否已按升序排序。

参数

  • x []int - 要检查的切片

返回值

  • bool - 是否已排序

示例

package main

import (
    "fmt"
    "sort"
)

func main() {
    nums1 := []int{1, 2, 3, 4, 5}
    nums2 := []int{1, 3, 2, 4, 5}
    
    fmt.Println(sort.IntsAreSorted(nums1)) // true
    fmt.Println(sort.IntsAreSorted(nums2)) // false
}

I

IsSorted

func IsSorted(data Interface) bool

功能: 检查实现了 Interface 的数据是否已排序。

参数

  • data Interface - 要检查的数据

返回值

  • bool - 是否已排序

示例

package main

import (
    "fmt"
    "sort"
)

type Person struct {
    Name string
    Age  int
}

type ByAge []Person

func (a ByAge) Len() int           { return len(a) }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
func (a ByAge) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }

func main() {
    people1 := []Person{{"Alice", 20}, {"Bob", 25}, {"Charlie", 30}}
    people2 := []Person{{"Alice", 20}, {"Charlie", 30}, {"Bob", 25}}
    
    fmt.Println(sort.IsSorted(ByAge(people1))) // true
    fmt.Println(sort.IsSorted(ByAge(people2))) // false
}

R

Reverse

func Reverse(data Interface) Interface

功能: 包装一个 Interface 以反转排序顺序(降序)。

参数

  • data Interface - 要反转的数据

返回值

  • Interface - 反转后的 Interface

示例

package main

import (
    "fmt"
    "sort"
)

func main() {
    nums := []int{1, 2, 3, 4, 5}
    
    // 降序排序
    sort.Sort(sort.Reverse(sort.IntSlice(nums)))
    fmt.Println(nums) // [5 4 3 2 1]
}

S

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

功能: 使用二分查找找到第一个使 f(i) 为 true 的索引 i。

参数

  • n int - 搜索范围 [0, n)
  • f func(int) bool - 条件函数

返回值

  • int - 找到的索引,如果不存在返回 n

要求

  • f(i) 必须为 false 在前缀,true 在后缀

示例

package main

import (
    "fmt"
    "sort"
)

func main() {
    // 在已排序切片中查找第一个 >= 25 的位置
    ages := []int{18, 20, 22, 25, 28, 30}
    
    idx := sort.Search(len(ages), func(i int) bool {
        return ages[i] >= 25
    })
    
    fmt.Printf("第一个 >= 25 的索引是 %d\n", idx) // 3
    if idx < len(ages) {
        fmt.Printf("值是 %d\n", ages[idx]) // 25
    }
}

SearchFloat64s

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

功能: 在已排序的 float64 切片中二分查找 x。

参数

  • a []float64 - 已排序的切片
  • x float64 - 要查找的值

返回值

  • int - x 的索引,或应插入的位置

示例

package main

import (
    "fmt"
    "sort"
)

func main() {
    nums := []float64{1.1, 2.2, 3.3, 4.4, 5.5}
    
    idx := sort.SearchFloat64s(nums, 3.3)
    fmt.Printf("3.3 在索引 %d\n", idx) // 2
    
    idx = sort.SearchFloat64s(nums, 3.0)
    fmt.Printf("3.0 应插入索引 %d\n", idx) // 2
}

SearchInts

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

功能: 在已排序的 int 切片中二分查找 x。

参数

  • a []int - 已排序的切片
  • x int - 要查找的值

返回值

  • int - x 的索引,或应插入的位置

示例

package main

import (
    "fmt"
    "sort"
)

func main() {
    nums := []int{1, 3, 5, 7, 9}
    
    idx := sort.SearchInts(nums, 5)
    fmt.Printf("5 在索引 %d\n", idx) // 2
    
    idx = sort.SearchInts(nums, 6)
    fmt.Printf("6 应插入索引 %d\n", idx) // 3
}

SearchStrings

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

功能: 在已排序的 string 切片中二分查找 x。

参数

  • a []string - 已排序的切片
  • x string - 要查找的值

返回值

  • int - x 的索引,或应插入的位置

示例

package main

import (
    "fmt"
    "sort"
)

func main() {
    names := []string{"Alice", "Bob", "Charlie", "David"}
    
    idx := sort.SearchStrings(names, "Charlie")
    fmt.Printf("Charlie 在索引 %d\n", idx) // 2
    
    idx = sort.SearchStrings(names, "Carol")
    fmt.Printf("Carol 应插入索引 %d\n", idx) // 2
}

Slice

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

功能: 使用提供的比较函数对切片进行排序。

参数

  • x any - 要排序的切片(任意类型)
  • less func(i, j int) bool - 比较函数

注意

  • 排序不稳定
  • 原地排序

示例

package main

import (
    "fmt"
    "sort"
)

type Person struct {
    Name string
    Age  int
}

func main() {
    people := []Person{
        {"Alice", 25},
        {"Bob", 20},
        {"Charlie", 30},
    }
    
    // 按年龄排序
    sort.Slice(people, func(i, j int) bool {
        return people[i].Age < people[j].Age
    })
    
    fmt.Println(people)
    // [{Bob 20} {Alice 25} {Charlie 30}]
}

SliceIsSorted

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

功能: 使用提供的比较函数检查切片是否已排序。

参数

  • x any - 要检查的切片
  • less func(i, j int) bool - 比较函数

返回值

  • bool - 是否已排序

示例

package main

import (
    "fmt"
    "sort"
)

type Person struct {
    Name string
    Age  int
}

func main() {
    people1 := []Person{{"Alice", 20}, {"Bob", 25}, {"Charlie", 30}}
    people2 := []Person{{"Alice", 25}, {"Bob", 20}, {"Charlie", 30}}
    
    sorted := func(p []Person) bool {
        return sort.SliceIsSorted(p, func(i, j int) bool {
            return p[i].Age < p[j].Age
        })
    }
    
    fmt.Println(sorted(people1)) // true
    fmt.Println(sorted(people2)) // false
}

SliceStable

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

功能: 使用提供的比较函数对切片进行稳定排序。

参数

  • x any - 要排序的切片
  • less func(i, j int) bool - 比较函数

注意

  • 稳定排序:相等元素保持原始顺序
  • 原地排序

示例

package main

import (
    "fmt"
    "sort"
)

type Person struct {
    Name string
    Age  int
}

func main() {
    people := []Person{
        {"Alice", 25},
        {"Bob", 20},
        {"Charlie", 25},
        {"David", 20},
    }
    
    // 按年龄稳定排序
    sort.SliceStable(people, func(i, j int) bool {
        return people[i].Age < people[j].Age
    })
    
    fmt.Println(people)
    // [{Bob 20} {David 20} {Alice 25} {Charlie 25}]
    // 注意:Bob 和 David 保持了原始顺序
}

Sort

func Sort(data Interface)

功能: 对实现了 Interface 的数据进行排序。

参数

  • data Interface - 要排序的数据

注意

  • 不稳定排序
  • 原地排序
  • 时间复杂度:O(n log n)

示例

package main

import (
    "fmt"
    "sort"
)

type Person struct {
    Name string
    Age  int
}

type ByAge []Person

func (a ByAge) Len() int           { return len(a) }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
func (a ByAge) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }

func main() {
    people := []Person{
        {"Alice", 25},
        {"Bob", 20},
        {"Charlie", 30},
    }
    
    sort.Sort(ByAge(people))
    fmt.Println(people)
    // [{Bob 20} {Alice 25} {Charlie 30}]
}

Stable

func Stable(data Interface)

功能: 对实现了 Interface 的数据进行稳定排序。

参数

  • data Interface - 要排序的数据

注意

  • 稳定排序:相等元素保持原始顺序
  • 原地排序
  • 时间复杂度:O(n log n)

示例

package main

import (
    "fmt"
    "sort"
)

type Person struct {
    Name string
    Age  int
}

type ByAge []Person

func (a ByAge) Len() int           { return len(a) }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
func (a ByAge) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }

func main() {
    people := []Person{
        {"Alice", 25},
        {"Bob", 20},
        {"Charlie", 25},
        {"David", 20},
    }
    
    sort.Stable(ByAge(people))
    fmt.Println(people)
    // [{Bob 20} {David 20} {Alice 25} {Charlie 25}]
}

S

Strings

func Strings(x []string)

功能: 对 string 切片进行升序排序。

参数

  • x []string - 要排序的切片

注意

  • 原地排序

示例

package main

import (
    "fmt"
    "sort"
)

func main() {
    names := []string{"Charlie", "Alice", "Bob"}
    sort.Strings(names)
    fmt.Println(names) // [Alice Bob Charlie]
}

StringsAreSorted

func StringsAreSorted(x []string) bool

功能: 检查 string 切片是否已按升序排序。

参数

  • x []string - 要检查的切片

返回值

  • bool - 是否已排序

示例

package main

import (
    "fmt"
    "sort"
)

func main() {
    names1 := []string{"Alice", "Bob", "Charlie"}
    names2 := []string{"Charlie", "Alice", "Bob"}
    
    fmt.Println(sort.StringsAreSorted(names1)) // true
    fmt.Println(sort.StringsAreSorted(names2)) // false
}

典型示例

示例 1:基本类型排序

package main

import (
    "fmt"
    "sort"
)

func main() {
    // int 排序
    nums := []int{5, 2, 8, 1, 9}
    sort.Ints(nums)
    fmt.Println("Ints:", nums)
    
    // float64 排序
    floats := []float64{3.14, 1.59, 2.65}
    sort.Float64s(floats)
    fmt.Println("Float64s:", floats)
    
    // string 排序
    names := []string{"Charlie", "Alice", "Bob"}
    sort.Strings(names)
    fmt.Println("Strings:", names)
}

运行结果

Ints: [1 2 5 8 9]
Float64s: [1.59 2.65 3.14]
Strings: [Alice Bob Charlie]

示例 2:自定义类型排序

package main

import (
    "fmt"
    "sort"
)

type Student struct {
    Name  string
    Score int
    Age   int
}

type ByScore []Student

func (s ByScore) Len() int           { return len(s) }
func (s ByScore) Less(i, j int) bool { return s[i].Score < s[j].Score }
func (s ByScore) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }

func main() {
    students := []Student{
        {"Alice", 85, 20},
        {"Bob", 92, 21},
        {"Charlie", 78, 19},
    }
    
    sort.Sort(ByScore(students))
    fmt.Println("按分数排序:", students)
}

运行结果

按分数排序:[{Charlie 78 19} {Alice 85 20} {Bob 92 21}]

示例 3:使用 Slice 函数排序

package main

import (
    "fmt"
    "sort"
)

type Student struct {
    Name  string
    Score int
}

func main() {
    students := []Student{
        {"Alice", 85},
        {"Bob", 92},
        {"Charlie", 78},
    }
    
    // 使用 Slice 函数,无需实现 Interface
    sort.Slice(students, func(i, j int) bool {
        return students[i].Score < students[j].Score
    })
    
    fmt.Println(students)
}

运行结果

[{Charlie 78} {Alice 85} {Bob 92}]

示例 4:多字段排序

package main

import (
    "fmt"
    "sort"
)

type Person struct {
    Name string
    Age  int
}

func main() {
    people := []Person{
        {"Alice", 25},
        {"Bob", 20},
        {"Alice", 20},
        {"Bob", 25},
    }
    
    // 先按姓名,再按年龄排序
    sort.Slice(people, func(i, j int) bool {
        if people[i].Name != people[j].Name {
            return people[i].Name < people[j].Name
        }
        return people[i].Age < people[j].Age
    })
    
    fmt.Println(people)
    // [{Alice 20} {Alice 25} {Bob 20} {Bob 25}]
}

示例 5:稳定排序

package main

import (
    "fmt"
    "sort"
)

type Task struct {
    Name     string
    Priority int
}

func main() {
    tasks := []Task{
        {"Task1", 2},
        {"Task2", 1},
        {"Task3", 2},
        {"Task4", 1},
    }
    
    // 不稳定排序
    sort.Slice(tasks, func(i, j int) bool {
        return tasks[i].Priority < tasks[j].Priority
    })
    fmt.Println("不稳定:", tasks)
    
    // 重置
    tasks = []Task{
        {"Task1", 2},
        {"Task2", 1},
        {"Task3", 2},
        {"Task4", 1},
    }
    
    // 稳定排序
    sort.SliceStable(tasks, func(i, j int) bool {
        return tasks[i].Priority < tasks[j].Priority
    })
    fmt.Println("稳定:", tasks)
}

运行结果

不稳定:[{Task2 1} {Task4 1} {Task3 2} {Task1 2}]
稳定:[{Task2 1} {Task4 1} {Task1 2} {Task3 2}]

示例 6:降序排序

package main

import (
    "fmt"
    "sort"
)

func main() {
    nums := []int{1, 2, 3, 4, 5}
    
    // 降序排序
    sort.Sort(sort.Reverse(sort.IntSlice(nums)))
    fmt.Println("降序:", nums) // [5 4 3 2 1]
}

示例 7:二分查找

package main

import (
    "fmt"
    "sort"
)

func main() {
    nums := []int{1, 3, 5, 7, 9}
    
    // 查找元素
    idx := sort.SearchInts(nums, 5)
    fmt.Printf("5 在索引 %d\n", idx)
    
    // 查找不存在的元素
    idx = sort.SearchInts(nums, 6)
    fmt.Printf("6 应插入索引 %d\n", idx)
    
    // 使用 Search 函数
    idx = sort.Search(len(nums), func(i int) bool {
        return nums[i] >= 7
    })
    fmt.Printf("第一个 >= 7 的索引是 %d\n", idx)
}

运行结果

5 在索引 2
6 应插入索引 3
第一个 >= 7 的索引是 3

示例 8:检查是否已排序

package main

import (
    "fmt"
    "sort"
)

type Person struct {
    Name string
    Age  int
}

func main() {
    people1 := []Person{{"Alice", 20}, {"Bob", 25}, {"Charlie", 30}}
    people2 := []Person{{"Alice", 25}, {"Bob", 20}, {"Charlie", 30}}
    
    fmt.Println("people1 已排序:", sort.SliceIsSorted(people1, func(i, j int) bool {
        return people1[i].Age < people1[j].Age
    }))
    
    fmt.Println("people2 已排序:", sort.SliceIsSorted(people2, func(i, j int) bool {
        return people2[i].Age < people2[j].Age
    }))
}

运行结果

people1 已排序:true
people2 已排序:false

最佳实践

1. 优先使用便捷函数

// ✅ 推荐:使用便捷函数
sort.Ints(nums)
sort.Strings(names)

// ❌ 不推荐:手动实现 Interface
sort.Sort(sort.IntSlice(nums))

2. 使用 Slice 函数简化代码

// ✅ 推荐:使用 Slice
sort.Slice(people, func(i, j int) bool {
    return people[i].Age < people[j].Age
})

// ❌ 不推荐:实现完整 Interface(除非需要复用)
type ByAge []Person
func (a ByAge) Len() int { ... }
func (a ByAge) Less(i, j int) bool { ... }
func (a ByAge) Swap(i, j int) { ... }

3. 需要保持顺序时使用稳定排序

// ✅ 需要保持相等元素原始顺序
sort.SliceStable(people, func(i, j int) bool {
    return people[i].Age < people[j].Age
})

// ❌ 不关心顺序时使用普通排序(性能更好)
sort.Slice(people, func(i, j int) bool {
    return people[i].Age < people[j].Age
})

4. 降序排序使用 Reverse

// ✅ 降序排序
sort.Sort(sort.Reverse(sort.IntSlice(nums)))

// 或者使用 Slice
sort.Slice(nums, func(i, j int) bool {
    return nums[i] > nums[j]
})

5. 多字段排序使用链式比较

// ✅ 多字段排序
sort.Slice(people, func(i, j int) bool {
    if people[i].Name != people[j].Name {
        return people[i].Name < people[j].Name
    }
    return people[i].Age < people[j].Age
})

与其他包配合

与 slices 包配合

package main

import (
    "fmt"
    "slices"
    "sort"
)

func main() {
    nums := []int{5, 2, 8, 1, 9}
    
    // 使用 slices 包(Go 1.21+)
    slices.Sort(nums)
    fmt.Println("slices:", nums)
    
    // 使用 sort 包
    sort.Ints(nums)
    fmt.Println("sort:", nums)
    
    // 检查是否已排序
    fmt.Println("IsSorted:", slices.IsSorted(nums))
    fmt.Println("AreSorted:", sort.IntsAreSorted(nums))
}

使用 cmp 包进行比较

package main

import (
    "cmp"
    "fmt"
    "sort"
)

type Item struct {
    Name  string
    Value int
}

func main() {
    items := []Item{
        {"Apple", 5},
        {"Banana", 3},
        {"Cherry", 8},
    }
    
    // 使用 cmp.Compare
    sort.Slice(items, func(i, j int) bool {
        return cmp.Compare(items[i].Value, items[j].Value) < 0
    })
    
    fmt.Println(items)
}

注意事项

限制

  1. 排序稳定性

    • SortSlice 是不稳定排序
    • StableSliceStable 是稳定排序
  2. 性能考虑

    • 时间复杂度:O(n log n)
    • 空间复杂度:O(log n)(递归栈)
  3. NaN 处理

    • Float64Slice 将 NaN 排在最后
  4. 原地排序

    • 所有排序函数都会修改原切片

使用建议

  1. 确保比较函数正确

    // ❌ 错误:使用 <= 会导致 panic
    sort.Slice(nums, func(i, j int) bool {
        return nums[i] <= nums[j] // 错误!
    })
    
    // ✅ 正确:使用 <
    sort.Slice(nums, func(i, j int) bool {
        return nums[i] < nums[j] // 正确
    })
    
  2. 检查切片是否为空

    if len(nums) <= 1 {
        return // 无需排序
    }
    sort.Ints(nums)
    
  3. 理解稳定性需求

    // 如果需要保持相等元素的原始顺序
    sort.SliceStable(items, less)
    
    // 如果不需要,使用更快的不稳定排序
    sort.Slice(items, less)
    

快速参考

函数速查表

函数功能稳定性
Find二分查找-
Float64s排序 float64 切片不稳定
Float64sAreSorted检查 float64 切片-
Ints排序 int 切片不稳定
IntsAreSorted检查 int 切片-
IsSorted检查 Interface-
Reverse反转排序顺序-
Search二分查找-
SearchFloat64s查找 float64-
SearchInts查找 int-
SearchStrings查找 string-
Slice使用函数排序不稳定
SliceIsSorted使用函数检查-
SliceStable稳定排序稳定
Sort排序 Interface不稳定
Stable稳定排序 Interface稳定
Strings排序 string 切片不稳定
StringsAreSorted检查 string 切片-

类型速查表

类型描述方法
Interface排序接口Len, Less, Swap
IntSliceint 切片类型Len, Less, Swap, Sort, Search
Float64Slicefloat64 切片类型Len, Less, Swap, Sort, Search
StringSlicestring 切片类型Len, Less, Swap, Sort, Search

常见模式

// 1. 基本类型排序
sort.Ints(nums)
sort.Float64s(floats)
sort.Strings(names)

// 2. 降序排序
sort.Sort(sort.Reverse(sort.IntSlice(nums)))

// 3. 自定义类型排序
sort.Slice(items, func(i, j int) bool {
    return items[i].Value < items[j].Value
})

// 4. 稳定排序
sort.SliceStable(items, func(i, j int) bool {
    return items[i].Value < items[j].Value
})

// 5. 二分查找
idx := sort.SearchInts(sortedNums, target)

// 6. 检查是否已排序
if sort.IntsAreSorted(nums) {
    // ...
}

// 7. 多字段排序
sort.Slice(people, func(i, j int) bool {
    if people[i].Name != people[j].Name {
        return people[i].Name < people[j].Name
    }
    return people[i].Age < people[j].Age
})

比较函数要求

// Less 函数必须满足:
// 1. 反对称性:Less(i, j) 和 Less(j, i) 不能同时为 true
// 2. 传递性:如果 Less(i, j) 和 Less(j, k) 为 true,则 Less(i, k) 必须为 true
// 3. 使用 < 而不是 <=

// ✅ 正确
func Less(i, j int) bool {
    return data[i] < data[j]
}

// ❌ 错误:使用 <= 会导致 panic
func Less(i, j int) bool {
    return data[i] <= data[j]
}

总结

sort 包是 Go 标准库中用于排序的核心包,提供了丰富的排序功能。

核心优势

  • ✅ 支持任意类型排序(通过 Interface)
  • ✅ 提供便捷函数(Ints、Float64s、Strings)
  • ✅ 支持稳定和不稳定排序
  • ✅ 提供二分查找功能
  • ✅ 性能优秀(O(n log n))

重要限制

  • ⚠️ Sort 和 Slice 是不稳定排序
  • ⚠️ 所有排序都是原地排序
  • ⚠️ 比较函数必须使用 < 而不是 <=

主要用途

  • 基本类型切片排序
  • 自定义类型排序
  • 使用比较函数排序
  • 检查切片是否已排序
  • 二分查找

使用建议

  1. 优先使用便捷函数
  2. 使用 Slice 函数简化代码
  3. 需要保持顺序时使用稳定排序
  4. 确保比较函数正确(使用 <)
  5. 理解稳定性和性能权衡

Go 1.21+ 替代方案

  • 考虑使用 slices 包(基于泛型)
  • slices.Sortslices.SortFunc