diff options
| author | Graydon Hoare <graydon@mozilla.com> | 2013-01-04 13:52:18 -0800 |
|---|---|---|
| committer | Graydon Hoare <graydon@mozilla.com> | 2013-04-18 14:39:40 -0700 |
| commit | 14b7277c4fe6fe7ef26a28931962d8557e2670a7 (patch) | |
| tree | 289add5430c55677491b6b3ff460ec45c6bf0d0c | |
| parent | 2a864852774e924f1f9bb68da34adca736211545 (diff) | |
| download | rust-14b7277c4fe6fe7ef26a28931962d8557e2670a7.tar.gz rust-14b7277c4fe6fe7ef26a28931962d8557e2670a7.zip | |
core: add vec::bsearch.
| -rw-r--r-- | src/libcore/vec.rs | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index eebe6a7a37f..01d1a57d78c 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -1223,6 +1223,46 @@ pub fn rposition_between<T>(v: &[T], start: uint, end: uint, None } + + +/** + * Binary search a sorted vector with a comparator function. + * + * The comparator should implement an order consistent with the sort + * order of the underlying vector, returning an order code that indicates + * whether its argument is `Less`, `Equal` or `Greater` the desired target. + * + * Returns the index where the comparator returned `Equal`, or `None` if + * not found. + */ +pub pure fn bsearch<T>(v: &[T], f: &fn(&T) -> Ordering) -> Option<uint> { + let mut base : uint = 0; + let mut lim : uint = v.len(); + + while lim != 0 { + let ix = base + (lim >> 1); + match f(&v[ix]) { + Equal => return Some(ix), + Less => { + base = ix + 1; + lim -= 1; + } + Greater => () + } + lim >>= 1; + } + return None; +} + +/** + * Binary search a sorted vector for a given element. + * + * Returns the index of the element or None if not found. + */ +pub pure fn bsearch_elem<T:TotalOrd>(v: &[T], x: &T) -> Option<uint> { + bsearch(v, |p| p.cmp(x)) +} + // FIXME: if issue #586 gets implemented, could have a postcondition // saying the two result lists have the same length -- or, could // return a nominal record with a constraint saying that, instead of @@ -3711,6 +3751,51 @@ mod tests { } #[test] + fn test_bsearch_elem() { + fail_unless!(bsearch_elem([1,2,3,4,5], &5) == Some(4)); + fail_unless!(bsearch_elem([1,2,3,4,5], &4) == Some(3)); + fail_unless!(bsearch_elem([1,2,3,4,5], &3) == Some(2)); + fail_unless!(bsearch_elem([1,2,3,4,5], &2) == Some(1)); + fail_unless!(bsearch_elem([1,2,3,4,5], &1) == Some(0)); + + fail_unless!(bsearch_elem([2,4,6,8,10], &1) == None); + fail_unless!(bsearch_elem([2,4,6,8,10], &5) == None); + fail_unless!(bsearch_elem([2,4,6,8,10], &4) == Some(1)); + fail_unless!(bsearch_elem([2,4,6,8,10], &10) == Some(4)); + + fail_unless!(bsearch_elem([2,4,6,8], &1) == None); + fail_unless!(bsearch_elem([2,4,6,8], &5) == None); + fail_unless!(bsearch_elem([2,4,6,8], &4) == Some(1)); + fail_unless!(bsearch_elem([2,4,6,8], &8) == Some(3)); + + fail_unless!(bsearch_elem([2,4,6], &1) == None); + fail_unless!(bsearch_elem([2,4,6], &5) == None); + fail_unless!(bsearch_elem([2,4,6], &4) == Some(1)); + fail_unless!(bsearch_elem([2,4,6], &6) == Some(2)); + + fail_unless!(bsearch_elem([2,4], &1) == None); + fail_unless!(bsearch_elem([2,4], &5) == None); + fail_unless!(bsearch_elem([2,4], &2) == Some(0)); + fail_unless!(bsearch_elem([2,4], &4) == Some(1)); + + fail_unless!(bsearch_elem([2], &1) == None); + fail_unless!(bsearch_elem([2], &5) == None); + fail_unless!(bsearch_elem([2], &2) == Some(0)); + + fail_unless!(bsearch_elem([], &1) == None); + fail_unless!(bsearch_elem([], &5) == None); + + fail_unless!(bsearch_elem([1,1,1,1,1], &1) != None); + fail_unless!(bsearch_elem([1,1,1,1,2], &1) != None); + fail_unless!(bsearch_elem([1,1,1,2,2], &1) != None); + fail_unless!(bsearch_elem([1,1,2,2,2], &1) != None); + fail_unless!(bsearch_elem([1,2,2,2,2], &1) == Some(0)); + + fail_unless!(bsearch_elem([1,2,3,4,5], &6) == None); + fail_unless!(bsearch_elem([1,2,3,4,5], &0) == None); + } + + #[test] fn reverse_and_reversed() { let mut v: ~[int] = ~[10, 20]; assert!(v[0] == 10); |
