slice::binary_search¶
Level: reference · for working programmers
One line: Find a value in a sorted slice in O(log n) — and, when it is absent, learn where it would go.
Stable since 1.0.0.
Ok(i) means the value is at index i. Err(i) means it is absent, and i is the index it would have to be inserted at to keep the slice sorted — which is why the return type is a Result and not an Option: the failure case carries an answer. v.insert(i, x) after an Err(i) keeps a vector sorted.
Two rules:
- The slice must already be sorted, ascending by
Ord. On an unsorted slice the result is unspecified — not an error, not a panic, just a number that happens to fall out of the halving. Nothing checks. - Duplicates: any matching index. With
[1, 2, 2, 2, 3]and&2you may get 1, 2 or 3. For the first or last occurrence usepartition_point↗ with the right predicate.
binary_search_by and binary_search_by_key take a comparison closure and a key, mirroring the sort_by / sort_by_key pair — sort and search have to agree on the order.
Example¶
slice_binary_search.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.
fn main() {
let sorted = [1, 3, 5, 7, 9];
println!("{:?}", sorted.binary_search(&5));
println!("{:?} <- absent; 4 would go at index 2", sorted.binary_search(&4));
println!("{:?} <- absent; past the end", sorted.binary_search(&100));
// Err carries the insertion point, so this keeps a Vec sorted.
let mut v = vec![1, 3, 5, 7, 9];
for x in [4, 0, 10] {
let at = v.binary_search(&x).unwrap_or_else(|i| i);
v.insert(at, x);
}
println!("{v:?}");
// On an unsorted slice the answer is unspecified: not wrong, not an error.
let unsorted = [9, 1, 5, 3, 7];
println!("{:?} <- 5 IS in there, at index 2", unsorted.binary_search(&5));
// Duplicates: any one of the matching indices may come back.
let dups = [1, 2, 2, 2, 3];
println!("{:?}", dups.binary_search(&2));
println!("first 2 at {}", dups.partition_point(|&x| x < 2));
println!("past the last 2 at {}", dups.partition_point(|&x| x <= 2));
}
Verified output of slice_binary_search.rs — regenerated by tools/run_examples.py, never hand-typed.
Ok(2)
Err(2) <- absent; 4 would go at index 2
Err(5) <- absent; past the end
[0, 1, 3, 4, 5, 7, 9, 10]
Err(4) <- 5 IS in there, at index 2
Ok(3)
first 2 at 1
past the last 2 at 4
See also¶
slice::contains— a linear scan, no sorting neededslice::sort— what has to happen firstslice::get— once you have the index