1
0
mirror of https://github.com/golang/go synced 2024-11-22 01:04:40 -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:
Russ Cox 2010-11-18 07:16:09 -05:00
parent 3fa6dcaca4
commit 19f0e4603d

View File

@ -6,61 +6,68 @@
package sort
// Search uses binary search to find the index i for a value x in an indexable
// and sorted data structure of n elements. The argument function f captures
// the value to be searched for, how the elements are indexed, and how they are
// sorted. It will often be passed as a closure. For instance, given a slice
// of integers, []data, sorted in ascending order, the function
// Search uses binary search to find and return the smallest index i
// in [0, n) at which f(i) is false, assuming that on the range [0, n),
// f(i) == false implies f(i+1) == false. That is, Search requires that
// f is true for some (possibly empty) prefix of the input range [0, n)
// 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
// by the function must be "less" if the elements are sorted in ascending
// order or "greater" if they are sorted in descending order.
// The function f will be called with values of i in the range 0 to n-1.
//
// For brevity, this discussion assumes ascending sort order. For descending
// order, replace < with >, and swap 'smaller' with 'larger'.
// For instance, given a slice data sorted in ascending order,
// the call Search(len(data), func(i int) bool { return data[i] < 23 })
// returns the smallest index i such that data[i] >= 23. If the caller
// wants to find whether 23 is in the slice, it must test data[i] == 23
// separately.
//
// 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
// assumed to be larger than any x. Thus 0 <= i <= n and i is the smallest
// index of x if x is present in the data. It is the responsibility of
// the caller to verify the actual presence by testing if i < n and
// 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]
// x := 23
// i := sort.Search(len(data), func(i int) bool { return data[i] < x })
// if i < len(data) && data[i] == x {
// // x is present at data[i]
// } 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 {
// Define f(-1) == true and f(n) == false.
// Invariant: f(i-1) == true, f(j) == false.
i, j := 0, n
for i+1 < j {
for i < j {
h := i + (j-i)/2 // avoid overflow when computing h
// i < h < j
// i h < j
if f(h) {
// data[h] < x
i = h + 1
i = h + 1 // preserves f(i-1) == true
} else {
// x <= data[h]
j = h
j = h // preserves f(j) == false
}
}
// test the final element that the loop did not
if i < j && f(i) {
// data[i] < x
i++
}
// i == j, f(i-1) == true, and f(j) (= f(i)) == false => answer is i.
return i
}