mirror of
https://github.com/golang/go
synced 2024-11-25 04:47:57 -07:00
sort: edit doc comment for Search
Change comment to be more generic, with indexed data structure search as one common use case. Fix typo []data. R=gri, rog CC=golang-dev https://golang.org/cl/3159041
This commit is contained in:
parent
3fa6dcaca4
commit
19f0e4603d
@ -6,61 +6,68 @@
|
|||||||
|
|
||||||
package sort
|
package sort
|
||||||
|
|
||||||
// Search uses binary search to find the index i for a value x in an indexable
|
// Search uses binary search to find and return the smallest index i
|
||||||
// and sorted data structure of n elements. The argument function f captures
|
// in [0, n) at which f(i) is false, assuming that on the range [0, n),
|
||||||
// the value to be searched for, how the elements are indexed, and how they are
|
// f(i) == false implies f(i+1) == false. That is, Search requires that
|
||||||
// sorted. It will often be passed as a closure. For instance, given a slice
|
// f is true for some (possibly empty) prefix of the input range [0, n)
|
||||||
// of integers, []data, sorted in ascending order, the function
|
// and then false for the (possibly empty) remainder; Search returns
|
||||||
|
// the first false index. If there is no such index, Search returns n.
|
||||||
|
// Search calls f(i) only for i in the range [0, n).
|
||||||
//
|
//
|
||||||
// func(i int) bool { return data[i] < 23 }
|
// A common use of Search is to find the index i for a value x in
|
||||||
|
// a sorted, indexable data structure like an array or slice.
|
||||||
|
// In this case, the argument f, typically a closure, captures the value
|
||||||
|
// to be searched for, and how the data structure is indexed and
|
||||||
|
// ordered.
|
||||||
//
|
//
|
||||||
// can be used to search for the value 23 in data. The relationship expressed
|
// For instance, given a slice data sorted in ascending order,
|
||||||
// by the function must be "less" if the elements are sorted in ascending
|
// the call Search(len(data), func(i int) bool { return data[i] < 23 })
|
||||||
// order or "greater" if they are sorted in descending order.
|
// returns the smallest index i such that data[i] >= 23. If the caller
|
||||||
// The function f will be called with values of i in the range 0 to n-1.
|
// wants to find whether 23 is in the slice, it must test data[i] == 23
|
||||||
//
|
// separately.
|
||||||
// For brevity, this discussion assumes ascending sort order. For descending
|
|
||||||
// order, replace < with >, and swap 'smaller' with 'larger'.
|
|
||||||
//
|
//
|
||||||
// Search returns the index i with:
|
// Searching data sorted in descending order would use the >
|
||||||
|
// operator instead of the < operator.
|
||||||
//
|
//
|
||||||
// data[i-1] < x && x <= data[i]
|
// To complete the example above, the following code tries to find the value
|
||||||
|
// x in an integer slice data sorted in ascending order:
|
||||||
//
|
//
|
||||||
// where data[-1] is assumed to be smaller than any x and data[n] is
|
// x := 23
|
||||||
// assumed to be larger than any x. Thus 0 <= i <= n and i is the smallest
|
// i := sort.Search(len(data), func(i int) bool { return data[i] < x })
|
||||||
// index of x if x is present in the data. It is the responsibility of
|
// if i < len(data) && data[i] == x {
|
||||||
// the caller to verify the actual presence by testing if i < n and
|
// // x is present at data[i]
|
||||||
// data[i] == x.
|
|
||||||
//
|
|
||||||
// To complete the example above, the following code tries to find the element
|
|
||||||
// elem in an integer slice data sorted in ascending order:
|
|
||||||
//
|
|
||||||
// elem := 23
|
|
||||||
// i := sort.Search(len(data), func(i int) bool { return data[i] < elem })
|
|
||||||
// if i < len(data) && data[i] == elem {
|
|
||||||
// // elem is present at data[i]
|
|
||||||
// } else {
|
// } else {
|
||||||
// // elem is not present in data
|
// // x is not present in data,
|
||||||
|
// // but i is the index where it would be inserted.
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// As a more whimsical example, this program guesses your number:
|
||||||
|
//
|
||||||
|
// func GuessingGame() {
|
||||||
|
// var s string
|
||||||
|
// fmt.Printf("Pick an integer from 0 to 100.\n")
|
||||||
|
// answer := sort.Search(100, func(i int) bool {
|
||||||
|
// fmt.Printf("Is your number > %d? ", i)
|
||||||
|
// fmt.Scanf("%s", &s)
|
||||||
|
// return s != "" && s[0] == 'y'
|
||||||
|
// })
|
||||||
|
// fmt.Printf("Your number is %d.\n", answer)
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
func Search(n int, f func(int) bool) int {
|
func Search(n int, f func(int) bool) int {
|
||||||
|
// Define f(-1) == true and f(n) == false.
|
||||||
|
// Invariant: f(i-1) == true, f(j) == false.
|
||||||
i, j := 0, n
|
i, j := 0, n
|
||||||
for i+1 < j {
|
for i < j {
|
||||||
h := i + (j-i)/2 // avoid overflow when computing h
|
h := i + (j-i)/2 // avoid overflow when computing h
|
||||||
// i < h < j
|
// i ≤ h < j
|
||||||
if f(h) {
|
if f(h) {
|
||||||
// data[h] < x
|
i = h + 1 // preserves f(i-1) == true
|
||||||
i = h + 1
|
|
||||||
} else {
|
} else {
|
||||||
// x <= data[h]
|
j = h // preserves f(j) == false
|
||||||
j = h
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// test the final element that the loop did not
|
// i == j, f(i-1) == true, and f(j) (= f(i)) == false => answer is i.
|
||||||
if i < j && f(i) {
|
|
||||||
// data[i] < x
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user