Go 语言标准库之 sort 包
sort 包实现了四种基本排序算法:插入排序(希尔排序)、归并排序、堆排序和快速排序,这四种排序方法是不公开的,它们只被用于 sort 包内部使用。在实际使用中,对数据集合排序时不必考虑应当选择哪一种排序方法,sort 包会根据实际数据自动选择高效的排序算法。
sort.Interface 接口
实现了sort.interface
的类型(一般为集合),都可以使用 sort 包中函数进行排序 ,sort.Interface
接口定义如下:
type Interface interface {
// Len 方法返回集合中的元素个数
Len() int
// Less 方法报告索引 i 的元素是否比索引 j 的元素小
Less(i, j int) bool
// Swap 方法交换索引 i 和 j 的两个元素
Swap(i, j int)
}
自定义类型排序
Sort/Stable 函数
// 对 data 进行排序,不保证稳定性,即相等元素的相对次序可能改变
// Sort 调用 1 次 data.Len 确定长度,调用 O(n*log(n)) 次 data.Less 和 data.Swap
func Sort(data Interface)
// 对 data 进行排序,保证排序的稳定性,即相等元素的相对次序不变
// Sort 调用 1 次 data.Len,O(n*log(n)) 次 data.Less 和 O(n*log(n)*log(n)) 次 data.Swap
func Stable(data Interface)
// 包装一个 sort.Interface 接口并返回一个新的 sort.Interface 接口,对该接口排序可生成递减序列
func Reverse(data Interface) Interface
// 判断 data 是否已经被排序
func IsSorted(data Interface) bool
☕️ 示例代码
package main
import (
"fmt"
"sort"
)
type Student struct {
Name string
Age int
}
type StudentSlice []Student
// 实现 sort.Interface 接口
func (ss StudentSlice) Len() int {
return len(ss)
}
func (ss StudentSlice) Less(i, j int) bool {
return ss[i].Age < ss[j].Age
}
func (ss StudentSlice) Swap(i, j int) {
ss[i], ss[j] = ss[j], ss[i]
}
func main() {
ss := StudentSlice{
{"Alice", 18},
{"Bob", 20},
{"Allen", 16},
{"Michelle", 18},
{"James", 24},
}
// 按照年龄递增排序
sort.Sort(ss)
fmt.Println(ss) // [{Allen 16} {Alice 18} {Michelle 18} {Bob 20} {James 24}]
// 判断是否已经被排序
fmt.Println(sort.IsSorted(ss)) // true
// 按照年龄递减排序
sort.Sort(sort.Reverse(ss))
fmt.Println(ss) // [{James 24} {Bob 20} {Alice 18} {Michelle 18} {Allen 16}]
// 判断是否已经被排序
fmt.Println(sort.IsSorted(ss)) // false
}
Slice/SliceStable 函数
在前面Sort/Stable
函数的排序中,自定义类型的切片需要实现sort.Interface
接口,在代码上不太简洁。Go 提供Slice/SliceStable
函数只需传入一个待排序的切片,一个回调函数即可进行排序。需要注意,除了下列三个函数,sort 包下其它排序函数的实现原理都是通过sort.Interface
接口,后文会进行分析。
// 使用 less 函数定义的规则对切片 x 进行排序,不保证排序的稳定性,x 不是切片会报 panic
func Slice(x interface{}, less func(i, j int) bool)
// 使用 less 函数定义的规则对切片 x 进行排序,保证排序的稳定性,x 不是切片会报 panic
func SliceStable(x interface{}, less func(i, j int) bool)
// 判断切片 x 根据 less 函数定义的规则是否是有序的,x 不是切片会报 panic
func SliceIsSorted(x interface{}, less func(i, j int) bool)
// 在长度为 n 的升序序列中使用二分法查询满足 f(i) = true 的索引位置,判断条件必须为 >=
func Search(n int, f func(int) bool) int
⭐️ 示例代码
package main
import (
"fmt"
"sort"
)
type Student struct {
Name string
Age int
}
func main() {
ss := []Student{
{"Alice", 18},
{"Bob", 20},
{"Allen", 16},
{"Michelle", 18},
{"James", 24},
}
less := func(i, j int) bool {
return ss[i].Age < ss[j].Age
}
// 按照年龄递增排序
sort.Slice(ss, less)
fmt.Println(ss) // [{Allen 16} {Alice 18} {Michelle 18} {Bob 20} {James 24}]
// 判断是否已经被排序
fmt.Println(sort.SliceIsSorted(ss, less)) // true
// 查找年龄等于 20 的学生的索引位置,判断条件必须为 >=
f := func(i int) bool {
return ss[i].Age >= 20
}
fmt.Println(sort.Search(len(ss), f)) // 3
}
基本数据类型排序
对于 int、float64 和 string 类型的切片,Go 语言进行了封装,可以直接调用 sort 包中的函数进行排序。
int 类型排序
// 在 sort 包下,Go 语言定义了 IntSlice 类型实现 sort.Interface 接口,用于 []int 排序
type IntSlice []int
// 实现 Interface 接口
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] }
// 等价调用 sort.Sort(x)
func (x IntSlice) Sort() { Sort(x) }
// 等价调用 sort.SearchInts(x, p)
func (x IntSlice) Search(p int) int { return SearchInts(x, p) }
// 对 x 进行递增排序
func Ints(x []int)
// 判断 x 是否为递增序列
func IntsAreSorted(x []int)
// 在递增序列的 a 中搜索 x,返回 x 的索引
// 如果查找不到,返回值是 x 应该插入 a 的位置(以保证 a 的递增顺序),返回值可以是 len(a)
func SearchInts(a []int, x int) int
✏️ 示例代码
package main
import (
"fmt"
"sort"
)
func main() {
// 递增排序
// 方式一:
intList1 := []int{2, 0, 1, 8, 0, 9, 2, 4, 1, 2}
sort.Ints(intList1)
fmt.Println(intList1) // [0 0 1 1 2 2 2 4 8 9]
// 方式二:
intList2 := []int{2, 0, 1, 8, 0, 9, 2, 4, 1, 2}
sort.Sort(sort.IntSlice(intList2))
fmt.Println(intList2) // [0 0 1 1 2 2 2 4 8 9]
// 方法三:
intList3 := []int{2, 0, 1, 8, 0, 9, 2, 4, 1, 2}
(sort.IntSlice(intList3)).Sort()
fmt.Println(intList3) // [0 0 1 1 2 2 2 4 8 9]
// 方式四
intList4 := []int{2, 0, 1, 8, 0, 9, 2, 4, 1, 2}
sort.Slice(intList4, func(i, j int) bool {
return intList4[i] < intList4[j]
})
fmt.Println(intList4) // [0 0 1 1 2 2 2 4 8 9]
// 判断是否为递增排序
// 方式一:
fmt.Println(sort.IntsAreSorted(intList1)) // true
// 方式二:
fmt.Println(sort.IsSorted(sort.IntSlice(intList2))) // true
// 递减排序
// 方式一:
intList5 := []int{2, 0, 1, 8, 0, 9, 2, 4, 1, 2}
sort.Sort(sort.Reverse(sort.IntSlice(intList5)))
fmt.Println(intList5) // [9 8 4 2 2 2 1 1 0 0]
// 方式二:
intList6 := []int{2, 0, 1, 8, 0, 9, 2, 4, 1, 2}
sort.Slice(intList6, func(i, j int) bool {
return intList6[i] > intList6[j]
})
fmt.Println(intList6) // [9 8 4 2 2 2 1 1 0 0]
// 在递增序列中搜索
intList7 := []int{0, 0, 1, 1, 2, 2, 2, 4, 8, 9}
// 方式一:
fmt.Println(sort.SearchInts(intList7, 2)) // 4
// 方式二:
fmt.Println((sort.IntSlice(intList7)).Search(2)) // 4
}
float64 类型排序
// 在 sort 包下,Go 语言定义了 Float64Slice 类型实现 sort.Interface 接口,用于 []float64 排序
type Float64Slice []float64
// 实现 Interface 接口
func (x Float64Slice) Len() int { return len(x) }
func (x Float64Slice) Less(i, j int) bool { return x[i] < x[j] || (isNaN(x[i]) && !isNaN(x[j])) }
func (x Float64Slice) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
// 等价调用 sort.Sort(x)
func (x Float64Slice) Sort() { Sort(x) }
// 等价调用 sort.SearchFloat64s(x, p)
func (x Float64Slice) Search(p float64) int { return SearchFloat64s(x, p) }
// 对 x 进行递增排序
func Float64s(x []float64)
// 判断 x 是否为递增序列
func Float64sAreSorted(x []float64)
// 在递增序列的 a 中搜索 x,返回 x 的索引
// 如果查找不到,返回值是 x 应该插入 a 的位置(以保证 a 的递增顺序),返回值可以是 len(a)
func SearchFloat64s(a []float64, x float64) int
📚 示例代码
package main
import (
"fmt"
"sort"
)
func main() {
// 递增排序
// 方式一:
floatList1 := []float64{4.2, 5.9, 12.3, 10.0, 50.4, 99.9, 31.4, 27.81828, 3.14}
sort.Float64s(floatList1)
fmt.Println(floatList1) // [3.14 4.2 5.9 10 12.3 27.81828 31.4 50.4 99.9]
// 方式二:
floatList2 := []float64{4.2, 5.9, 12.3, 10.0, 50.4, 99.9, 31.4, 27.81828, 3.14}
sort.Sort(sort.Float64Slice(floatList2))
fmt.Println(floatList2) // [3.14 4.2 5.9 10 12.3 27.81828 31.4 50.4 99.9]
// 方法三:
floatList3 := []float64{4.2, 5.9, 12.3, 10.0, 50.4, 99.9, 31.4, 27.81828, 3.14}
(sort.Float64Slice(floatList3)).Sort()
fmt.Println(floatList3) // [3.14 4.2 5.9 10 12.3 27.81828 31.4 50.4 99.9]
// 方式四
floatList4 := []float64{4.2, 5.9, 12.3, 10.0, 50.4, 99.9, 31.4, 27.81828, 3.14}
sort.Slice(floatList4, func(i, j int) bool {
return floatList4[i] < floatList4[j]
})
fmt.Println(floatList4) // [3.14 4.2 5.9 10 12.3 27.81828 31.4 50.4 99.9]
// 判断是否为递增排序
// 方式一:
fmt.Println(sort.Float64sAreSorted(floatList1)) // true
// 方式二:
fmt.Println(sort.IsSorted(sort.Float64Slice(floatList2))) // true
// 递减排序
// 方式一:
floatList5 := []float64{4.2, 5.9, 12.3, 10.0, 50.4, 99.9, 31.4, 27.81828, 3.14}
sort.Sort(sort.Reverse(sort.Float64Slice(floatList5)))
fmt.Println(floatList5) // [99.9 50.4 31.4 27.81828 12.3 10 5.9 4.2 3.14]
// 方式二:
floatList6 := []float64{4.2, 5.9, 12.3, 10.0, 50.4, 99.9, 31.4, 27.81828, 3.14}
sort.Slice(floatList6, func(i, j int) bool {
return floatList6[i] > floatList6[j]
})
fmt.Println(floatList6) // [99.9 50.4 31.4 27.81828 12.3 10 5.9 4.2 3.14]
// 在递增序列中搜索
floatList7 := []float64{3.14, 4.2, 5.9, 10, 12.3, 27.81828, 31.4, 50.4, 99.9}
// 方式一:
fmt.Println(sort.SearchFloat64s(floatList7, 12.3)) // 4
// 方式二:
fmt.Println((sort.Float64Slice(floatList7)).Search(12.3)) // 4
}
string 类型排序
// 在 sort 包下,Go 语言定义了 StringSlice 类型实现 sort.Interface 接口,用于 []string 排序
type StringSlice []string
// 实现 Interface 接口
func (x StringSlice) Len() int { return len(x) }
func (x StringSlice) Less(i, j int) bool { return x[i] < x[j] }
func (x StringSlice) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
// 等价调用 sort.Sort(x)
func (x StringSlice) Sort() { Sort(x) }
// 等价调用 sort.SearchStrings(x, p)
func (x StringSlice) Search(p string) int { return SearchStrings(x, p) }
// 对 x 进行递增排序
func Strings(x []string)
// 判断 x 是否为递增序列
func StringsAreSorted(x []string)
// 在递增序列的 a 中搜索 x,返回 x 的索引
// 如果查找不到,返回值是 x 应该插入 a 的位置(以保证 a 的递增顺序),返回值可以是 len(a)
func SearchStrings(a []string, x string) int
✌ 示例代码
package main
import (
"fmt"
"sort"
)
func main() {
// 递增排序
// 方式一:
stringList1 := []string{"o", "l", "d", "b", "o", "y", "g", "o", "l", "a", "n", "g"}
sort.Strings(stringList1)
fmt.Printf("%q\n", stringList1) // ["a" "b" "d" "g" "g" "l" "l" "n" "o" "o" "o" "y"]
// 方式二:
stringList2 := []string{"o", "l", "d", "b", "o", "y", "g", "o", "l", "a", "n", "g"}
sort.Sort(sort.StringSlice(stringList2))
fmt.Printf("%q\n", stringList2) // ["a" "b" "d" "g" "g" "l" "l" "n" "o" "o" "o" "y"]
// 方式三:
stringList3 := []string{"o", "l", "d", "b", "o", "y", "g", "o", "l", "a", "n", "g"}
(sort.StringSlice(stringList3)).Sort()
fmt.Printf("%q\n", stringList3) // ["a" "b" "d" "g" "g" "l" "l" "n" "o" "o" "o" "y"]
// 方式四
stringList4 := []string{"o", "l", "d", "b", "o", "y", "g", "o", "l", "a", "n", "g"}
sort.Slice(stringList4, func(i, j int) bool {
return stringList4[i] < stringList4[j]
})
fmt.Printf("%q\n", stringList4) // ["a" "b" "d" "g" "g" "l" "l" "n" "o" "o" "o" "y"]
// 判断是否为递增排序
// 方式一:
fmt.Println(sort.StringsAreSorted(stringList1)) // true
// 方式二:
fmt.Println(sort.IsSorted(sort.StringSlice(stringList2))) // true
// 递减排序
// 方式一:
stringList5 := []string{"o", "l", "d", "b", "o", "y", "g", "o", "l", "a", "n", "g"}
sort.Sort(sort.Reverse(sort.StringSlice(stringList5)))
fmt.Printf("%q\n", stringList5) // ["y" "o" "o" "o" "n" "l" "l" "g" "g" "d" "b" "a"]
// 方式二:
stringList6 := []string{"o", "l", "d", "b", "o", "y", "g", "o", "l", "a", "n", "g"}
sort.Slice(stringList6, func(i, j int) bool {
return stringList6[i] > stringList6[j]
})
fmt.Printf("%q\n", stringList6) // ["y" "o" "o" "o" "n" "l" "l" "g" "g" "d" "b" "a"]
// 在递增序列中搜索
stringList7 := []string{"a", "b", "d", "g", "g", "l", "l", "n", "o", "o", "o", "y"}
// 方式一:
fmt.Println(sort.SearchStrings(stringList7, "l")) // 5
// 方式二:
fmt.Println((sort.StringSlice(stringList7)).Search("l")) // 5
}
底层实现分析
sort.Sort 函数
// Sort 函数是一个不稳定方式排序,使用希尔快速、快速排序或者堆排序三种排序方式之一
func Sort(data Interface) {
n := data.Len()
// maxDepth(n) 返回 2*ceil(lg(n+1)),元素深度达到 2*ceil(lg(n+1)) 则选用堆排序
quickSort(data, 0, n, maxDepth(n))
}
// quickSort 会根据与元素深度自动选择使用希尔快速、快速排序或者堆排序三种排序方式之一
func quickSort(data Interface, a, b, maxDepth int) {
for b-a > 12 {
if maxDepth == 0 { // Use ShellSort for slices <= 12 elements
// 使用堆排序
heapSort(data, a, b)
return
}
maxDepth--
// 使用三向切分快速排序,通过 doPivot 进行快排的分区
mlo, mhi := doPivot(data, a, b)
// Avoiding recursion on the larger subproblem guarantees
// a stack depth of at most lg(b-a).
if mlo-a < b-mhi {
quickSort(data, a, mlo, maxDepth)
a = mhi // i.e., quickSort(data, mhi, b)
} else {
quickSort(data, mhi, b, maxDepth)
b = mlo // i.e., quickSort(data, a, mlo)
}
}
// 切片元素小于等于 12 个,使用希尔排序(希尔排序是插入排序的高效版本),间隔 d=6
if b-a > 1 {
// Do ShellSort pass with gap 6
// It could be written in this simplified form cause b-a <= 12
for i := a + 6; i < b; i++ {
if data.Less(i, i-6) {
data.Swap(i, i-6)
}
}
insertionSort(data, a, b)
}
}
// 堆排序
func heapSort(data Interface, a, b int) {
first := a
lo := 0
hi := b - a
// Build heap with greatest element at top.
for i := (hi - 1) / 2; i >= 0; i-- {
siftDown(data, i, hi, first)
}
// Pop elements, largest first, into end of data.
for i := hi - 1; i >= 0; i-- {
data.Swap(first, first+i)
siftDown(data, lo, i, first)
}
}
// siftDown implements the heap property on data[lo:hi].
// first is an offset into the array where the root of the heap lies.
func siftDown(data Interface, lo, hi, first int) {
root := lo
for {
child := 2*root + 1
if child >= hi {
break
}
if child+1 < hi && data.Less(first+child, first+child+1) {
child++
}
if !data.Less(first+root, first+child) {
return
}
data.Swap(first+root, first+child)
root = child
}
}
// 插入排序
// insertionSort sorts data[a:b] using insertion sort.
func insertionSort(data Interface, a, b int) {
for i := a + 1; i < b; i++ {
for j := i; j > a && data.Less(j, j-1); j-- {
data.Swap(j, j-1)
}
}
}
sort.Stable 函数
// Stable 是一个稳定方式的排序,使用归并排序
func Stable(data Interface) {
stable(data, data.Len())
}
// 这里用到的归并排序算法是一种原址排序算法:
// 首先,它把 slice 按照每 blockSize=20 个元素为一个 slice,进行插入排序
// 循环合并相邻的两个 block,每次循环 blockSize 扩大二倍,直到 blockSize > n 为止
func stable(data Interface, n int) {
// 初始 blockSize 设置为 20
blockSize := 20 // must be > 0
a, b := 0, blockSize
// 对每个块(以及剩余不足blockSize的一个块)进行插入排序
for b <= n {
insertionSort(data, a, b)
a = b
b += blockSize
}
insertionSort(data, a, n)
for blockSize < n {
a, b = 0, 2*blockSize
for b <= n {
// 每两个 blockSize 进行合并
symMerge(data, a, a+blockSize, b)
a = b
b += 2 * blockSize
}
// 剩余一个多 blockSize 进行合并
if m := a + blockSize; m < n {
symMerge(data, a, m, n)
}
blockSize *= 2
}
}
func symMerge(data Interface, a, m, b int) {
// Avoid unnecessary recursions of symMerge
// by direct insertion of data[a] into data[m:b]
// if data[a:m] only contains one element.
if m-a == 1 {
// Use binary search to find the lowest index i
// such that data[i] >= data[a] for m <= i < b.
// Exit the search loop with i == b in case no such index exists.
i := m
j := b
for i < j {
h := int(uint(i+j) >> 1)
if data.Less(h, a) {
i = h + 1
} else {
j = h
}
}
// Swap values until data[a] reaches the position before i.
for k := a; k < i-1; k++ {
data.Swap(k, k+1)
}
return
}
// Avoid unnecessary recursions of symMerge
// by direct insertion of data[m] into data[a:m]
// if data[m:b] only contains one element.
if b-m == 1 {
// Use binary search to find the lowest index i
// such that data[i] > data[m] for a <= i < m.
// Exit the search loop with i == m in case no such index exists.
i := a
j := m
for i < j {
h := int(uint(i+j) >> 1)
if !data.Less(m, h) {
i = h + 1
} else {
j = h
}
}
// Swap values until data[m] reaches the position i.
for k := m; k > i; k-- {
data.Swap(k, k-1)
}
return
}
mid := int(uint(a+b) >> 1)
n := mid + m
var start, r int
if m > mid {
start = n - b
r = mid
} else {
start = a
r = m
}
p := n - 1
for start < r {
c := int(uint(start+r) >> 1)
if !data.Less(p-c, c) {
start = c + 1
} else {
r = c
}
}
end := n - start
if start < m && m < end {
rotate(data, start, m, end)
}
if a < start && start < mid {
symMerge(data, a, start, mid)
}
if mid < end && end < b {
symMerge(data, mid, end, b)
}
}
sort.Slice 函数
// Slice 函数是一个不稳定方式排序,使用希尔快速、快速排序或者堆排序三种排序方式之一
// Slice sorts the slice x given the provided less function.
// It panics if x is not a slice.
//
// The sort is not guaranteed to be stable: equal elements
// may be reversed from their original order.
// For a stable sort, use SliceStable.
//
// The less function must satisfy the same requirements as
// the Interface type's Less method.
func Slice(x interface{}, less func(i, j int) bool) {
rv := reflectValueOf(x)
swap := reflectSwapper(x)
length := rv.Len()
// maxDepth(n) 返回 2*ceil(lg(n+1)),元素深度达到 2*ceil(lg(n+1)) 则选用堆排序
quickSort_func(lessSwap{less, swap}, 0, length, maxDepth(length))
}
// lessSwap is a pair of Less and Swap function for use with the
// auto-generated func-optimized variant of sort.go in
// zfuncversion.go.
type lessSwap struct {
Less func(i, j int) bool
Swap func(i, j int)
}
// quickSort_func 会根据与元素深度自动选择使用希尔快速、快速排序或者堆排序三种排序方式之一
// Auto-generated variant of sort.go:quickSort
func quickSort_func(data lessSwap, a, b, maxDepth int) {
for b-a > 12 {
if maxDepth == 0 {
// 使用堆排序
heapSort_func(data, a, b)
return
}
maxDepth--
// 使用三向切分快速排序,通过 doPivot_func 进行快排的分区
mlo, mhi := doPivot_func(data, a, b)
if mlo-a < b-mhi {
quickSort_func(data, a, mlo, maxDepth)
a = mhi
} else {
quickSort_func(data, mhi, b, maxDepth)
b = mlo
}
}
// 切片元素小于等于 12 个,使用希尔排序(希尔排序是插入排序的高效版本),间隔 d=6
if b-a > 1 {
for i := a + 6; i < b; i++ {
if data.Less(i, i-6) {
data.Swap(i, i-6)
}
}
insertionSort_func(data, a, b)
}
}
从上面可以看到,sort.Slice
调用的排序函数quickSort_func
的入参类型是data lessSwap
,而不是data Interface
,调用的插入排序、堆排序、快速排序函数也和sort.Sort
不同。sort.Slice
和sort.Sort
的实现原理是相同的,区别在于sort.Sort
通过传入实现sort.Interface
接口的对象获得Len()/Swap()/Less()
,而sort.Slice
是通过反射的方式获取Len()
和Swap()
,Less()
通过传参获得。因此,sort.Slice
传入切片和Less()
函数即可实现排序。
sort.SliceStable 函数
// SliceStable 是一个稳定方式的排序,使用归并排序
// SliceStable sorts the slice x using the provided less
// function, keeping equal elements in their original order.
// It panics if x is not a slice.
//
// The less function must satisfy the same requirements as
// the Interface type's Less method.
func SliceStable(x interface{}, less func(i, j int) bool) {
rv := reflectValueOf(x)
swap := reflectSwapper(x)
stable_func(lessSwap{less, swap}, rv.Len())
}
// lessSwap is a pair of Less and Swap function for use with the
// auto-generated func-optimized variant of sort.go in
// zfuncversion.go.
type lessSwap struct {
Less func(i, j int) bool
Swap func(i, j int)
}
// 这里用到的归并排序算法是一种原址排序算法:
// 首先,它把 slice 按照每 blockSize=20 个元素为一个 slice,进行插入排序
// 循环合并相邻的两个 block,每次循环 blockSize 扩大二倍,直到 blockSize > n 为止
// Auto-generated variant of sort.go:stable
func stable_func(data lessSwap, n int) {
blockSize := 20 // 初始 blockSize 设置为 20
a, b := 0, blockSize
// 对每个块(以及剩余不足blockSize的一个块)进行插入排序
for b <= n {
insertionSort_func(data, a, b)
a = b
b += blockSize
}
insertionSort_func(data, a, n)
for blockSize < n {
a, b = 0, 2*blockSize
for b <= n {
// 每两个 blockSize 进行合并
symMerge_func(data, a, a+blockSize, b)
a = b
b += 2 * blockSize
}
// 剩余一个多 blockSize 进行合并
if m := a + blockSize; m < n {
symMerge_func(data, a, m, n)
}
blockSize *= 2
}
}
和sort.Slice
一样,sort.SliceStable
调用的排序函数stable_func
的入参类型是data lessSwap
,不是data Interface
,通过反射的方式获取Len()
和Swap()
,Less()
通过传参获得。