mirror of
https://github.com/golang/go
synced 2024-11-08 09:36:24 -07:00
sort: update comments
- Describe requirements on Less more precisely. - Standardize on x for the variable name of the data being sorted (was variously a, p, slice). - Many other minor wording changes. Fixes #41951. Change-Id: Ic9e222a53ec035fcc3b5ddfc7f0eefbe1bb2890d Reviewed-on: https://go-review.googlesource.com/c/go/+/262657 Trust: Russ Cox <rsc@golang.org> Run-TryBot: Russ Cox <rsc@golang.org> Reviewed-by: Rob Pike <r@golang.org>
This commit is contained in:
parent
912262b806
commit
af8748054b
@ -4,34 +4,38 @@
|
||||
|
||||
package sort
|
||||
|
||||
// Slice sorts the provided slice given the provided less function.
|
||||
// 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. For a stable sort, use
|
||||
// SliceStable.
|
||||
// The sort is not guaranteed to be stable: equal elements
|
||||
// may be reversed from their original order.
|
||||
// For a stable sort, use SliceStable.
|
||||
//
|
||||
// The function panics if the provided interface is not a slice.
|
||||
func Slice(slice interface{}, less func(i, j int) bool) {
|
||||
rv := reflectValueOf(slice)
|
||||
swap := reflectSwapper(slice)
|
||||
// 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()
|
||||
quickSort_func(lessSwap{less, swap}, 0, length, maxDepth(length))
|
||||
}
|
||||
|
||||
// SliceStable sorts the provided slice given the provided less
|
||||
// function while keeping the original order of equal elements.
|
||||
// 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 function panics if the provided interface is not a slice.
|
||||
func SliceStable(slice interface{}, less func(i, j int) bool) {
|
||||
rv := reflectValueOf(slice)
|
||||
swap := reflectSwapper(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())
|
||||
}
|
||||
|
||||
// SliceIsSorted tests whether a slice is sorted.
|
||||
//
|
||||
// The function panics if the provided interface is not a slice.
|
||||
func SliceIsSorted(slice interface{}, less func(i, j int) bool) bool {
|
||||
rv := reflectValueOf(slice)
|
||||
// SliceIsSorted reports whether the slice x is sorted according to the provided less function.
|
||||
// It panics if x is not a slice.
|
||||
func SliceIsSorted(x interface{}, less func(i, j int) bool) bool {
|
||||
rv := reflectValueOf(x)
|
||||
n := rv.Len()
|
||||
for i := n - 1; i > 0; i-- {
|
||||
if less(i, i-1) {
|
||||
|
114
src/sort/sort.go
114
src/sort/sort.go
@ -4,30 +4,37 @@
|
||||
|
||||
//go:generate go run genzfunc.go
|
||||
|
||||
// Package sort provides primitives for sorting slices and user-defined
|
||||
// collections.
|
||||
// Package sort provides primitives for sorting slices and user-defined collections.
|
||||
package sort
|
||||
|
||||
// A type, typically a collection, that satisfies sort.Interface can be
|
||||
// sorted by the routines in this package. The methods require that the
|
||||
// elements of the collection be enumerated by an integer index.
|
||||
//
|
||||
// The sort routines require that the Less method implements a strict weak
|
||||
// ordering; see https://en.wikipedia.org/wiki/Weak_ordering.
|
||||
// The < operations on ints and strings are examples of such an ordering,
|
||||
// whereas the < operation on floating-point numbers is not, due to the
|
||||
// behavior of not-a-number (NaN) values.
|
||||
// An implementation of Interface can be sorted by the routines in this package.
|
||||
// The methods refer to elements of the underlying collection by integer index.
|
||||
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 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 a correctly implementation for floating-point values.
|
||||
Less(i, j int) bool
|
||||
|
||||
// Swap swaps the elements with indexes i and j.
|
||||
Swap(i, j int)
|
||||
}
|
||||
|
||||
// Insertion sort
|
||||
// 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-- {
|
||||
@ -36,7 +43,7 @@ func insertionSort(data Interface, a, b int) {
|
||||
}
|
||||
}
|
||||
|
||||
// siftDown implements the heap property on data[lo, hi).
|
||||
// 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
|
||||
@ -217,7 +224,7 @@ func quickSort(data Interface, a, b, maxDepth int) {
|
||||
}
|
||||
|
||||
// Sort sorts data.
|
||||
// It makes one call to data.Len to determine n, and O(n*log(n)) calls to
|
||||
// It makes one call to data.Len to determine n and O(n*log(n)) calls to
|
||||
// data.Less and data.Swap. The sort is not guaranteed to be stable.
|
||||
func Sort(data Interface) {
|
||||
n := data.Len()
|
||||
@ -274,61 +281,68 @@ func IsSorted(data Interface) bool {
|
||||
// IntSlice attaches the methods of Interface to []int, sorting in increasing order.
|
||||
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 (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 is a convenience method.
|
||||
func (p IntSlice) Sort() { Sort(p) }
|
||||
// Sort is a convenience method: x.Sort() calls Sort(x).
|
||||
func (x IntSlice) Sort() { Sort(x) }
|
||||
|
||||
// Float64Slice attaches the methods of Interface to []float64, sorting in increasing order.
|
||||
// In order to satisfy the ordering requirements of the Less method, not-a-number (NaN)
|
||||
// values are treated as less than other values.
|
||||
// Float64Slice implements Interface for a []float64, sorting in increasing order,
|
||||
// with not-a-number (NaN) values ordered before other values.
|
||||
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 (x Float64Slice) Len() int { return len(x) }
|
||||
|
||||
// Less reports whether x[i] should be ordered before x[j], as required by the sort Interface.
|
||||
// Note that floating-point comparison by itself is not a transitive relation: it does not
|
||||
// report a consistent ordering for not-a-number (NaN) values.
|
||||
// This implementation of Less places NaN values before any others, by using:
|
||||
//
|
||||
// x[i] < x[j] || (math.IsNaN(x[i]) && !math.IsNaN(x[j]))
|
||||
//
|
||||
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] }
|
||||
|
||||
// isNaN is a copy of math.IsNaN to avoid a dependency on the math package.
|
||||
func isNaN(f float64) bool {
|
||||
return f != f
|
||||
}
|
||||
|
||||
// Sort is a convenience method.
|
||||
func (p Float64Slice) Sort() { Sort(p) }
|
||||
// Sort is a convenience method: x.Sort() calls Sort(x).
|
||||
func (x Float64Slice) Sort() { Sort(x) }
|
||||
|
||||
// StringSlice attaches the methods of Interface to []string, sorting in increasing order.
|
||||
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 (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 is a convenience method.
|
||||
func (p StringSlice) Sort() { Sort(p) }
|
||||
// Sort is a convenience method: x.Sort() calls Sort(x).
|
||||
func (x StringSlice) Sort() { Sort(x) }
|
||||
|
||||
// Convenience wrappers for common cases
|
||||
|
||||
// Ints sorts a slice of ints in increasing order.
|
||||
func Ints(a []int) { Sort(IntSlice(a)) }
|
||||
func Ints(x []int) { Sort(IntSlice(x)) }
|
||||
|
||||
// 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)) }
|
||||
// Float64s sorts a slice of float64s in increasing order.
|
||||
// Not-a-number (NaN) values are ordered before other values.
|
||||
func Float64s(x []float64) { Sort(Float64Slice(x)) }
|
||||
|
||||
// Strings sorts a slice of strings in increasing order.
|
||||
func Strings(a []string) { Sort(StringSlice(a)) }
|
||||
func Strings(x []string) { Sort(StringSlice(x)) }
|
||||
|
||||
// IntsAreSorted tests whether a slice of ints is sorted in increasing order.
|
||||
func IntsAreSorted(a []int) bool { return IsSorted(IntSlice(a)) }
|
||||
// IntsAreSorted reports whether the slice x is sorted in increasing order.
|
||||
func IntsAreSorted(x []int) bool { return IsSorted(IntSlice(x)) }
|
||||
|
||||
// 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)) }
|
||||
// Float64sAreSorted reports whether the slice x is sorted in increasing order,
|
||||
// with not-a-number (NaN) values before any other values.
|
||||
func Float64sAreSorted(x []float64) bool { return IsSorted(Float64Slice(x)) }
|
||||
|
||||
// StringsAreSorted tests whether a slice of strings is sorted in increasing order.
|
||||
func StringsAreSorted(a []string) bool { return IsSorted(StringSlice(a)) }
|
||||
// StringsAreSorted reports whether the slice x is sorted in increasing order.
|
||||
func StringsAreSorted(x []string) bool { return IsSorted(StringSlice(x)) }
|
||||
|
||||
// Notes on stable sorting:
|
||||
// The used algorithms are simple and provable correct on all input and use
|
||||
@ -388,7 +402,7 @@ func stable(data Interface, n int) {
|
||||
}
|
||||
}
|
||||
|
||||
// SymMerge merges the two sorted subsequences data[a:m] and data[m:b] using
|
||||
// symMerge merges the two sorted subsequences data[a:m] and data[m:b] using
|
||||
// the SymMerge algorithm from Pok-Son Kim and Arne Kutzner, "Stable Minimum
|
||||
// Storage Merging by Symmetric Comparisons", in Susanne Albers and Tomasz
|
||||
// Radzik, editors, Algorithms - ESA 2004, volume 3221 of Lecture Notes in
|
||||
@ -489,10 +503,10 @@ func symMerge(data Interface, a, m, b int) {
|
||||
}
|
||||
}
|
||||
|
||||
// Rotate two consecutive blocks u = data[a:m] and v = data[m:b] in data:
|
||||
// rotate rotates two consecutive blocks u = data[a:m] and v = data[m:b] in data:
|
||||
// Data of the form 'x u v y' is changed to 'x v u y'.
|
||||
// Rotate performs at most b-a many calls to data.Swap.
|
||||
// Rotate assumes non-degenerate arguments: a < m && m < b.
|
||||
// rotate performs at most b-a many calls to data.Swap,
|
||||
// and it assumes non-degenerate arguments: a < m && m < b.
|
||||
func rotate(data Interface, a, m, b int) {
|
||||
i := m - a
|
||||
j := b - m
|
||||
|
Loading…
Reference in New Issue
Block a user