1 实现
rust已经有binary_search了,但不能很好的处理有重复元素的查找。
下面这个是我按照网上查找到的原理自己实现的,这个处理重复元素比较好,如果key有重复,那么查找到的总是最小的那个index
fn main() {
let s = [0, 0,0,0,0,1,1,1, 1, 1, 1, 2,2,3, 3, 5, 8, 13, 21, 34, 55];
let seek = 1;
let mut left = 0;
let mut right = s.len()-1;
let mut mid;
while left < right {
mid = (left + right) >> 1;
assert!(mid < right);
if s[mid] < seek {
left = mid + 1;
}else{
right = mid;
}
}
//自己实现的二分查找的结果
println!("search value:{}\nleft:{},right:{}\nfind:\n idx:{},value:{}",seek,left,right,left,s[left]);
//调用rust实现的二分查找
println!("{:?}",s.binary_search(&1));
}
Play地址:https://is.gd/1PJo67
运行结果:
search value:1
left:5,right:5
find:
idx:5,value:1
Ok(10)
自己实现的二分查找找到了第一个”1”的位置了,而rust自带的binary_search找到的并不一定是第一个”1”
2 简单的性能测试
做了个简单的bench,可以看到我的这个实现与库实现的差别很小,估计库也没有做优化了,先贴结果:
test bench_binary_search … bench: 42 ns/iter (+/- 9)
test bench_binary_search_lib … bench: 41 ns/iter (+/- 11)
这几个全局变量控制测试长度的
static test_len:usize = 1000;
static test_linear_key:u32 = 500;
static test_binary_key:u32 = 200;
注:因为rust自带的binary_search不能很好的处理key重复的情况,所以就用不重复的数组进行测试
2.1 自己实现的算法:
#[bench]
fn bench_binary_search(b: &mut Bencher) {
let mut v:Vec<u32> = Vec::with_capacity(test_len);
for i in (0..test_len) {
v.push(i as u32);
}
b.iter(|| {
let mut left = 0;
let mut right = test_len-1;
let mut mid = 0;
while left < right {
mid = (left + right) >> 1;
assert!(mid < right);
if v[mid] < test_binary_key {
left = mid + 1;
}else{
right = mid;
}
}
assert!((left == right) && (v[left] == test_binary_key));
});
}
2.2 使用库自带的二分查找:
#[bench]
fn bench_binary_search_lib(b: &mut Bencher) {
let mut v:Vec<u32> = Vec::with_capacity(test_len);
for i in (0..test_len) {
v.push(i as u32);
}
b.iter(|| {
if let Ok(idx) = v.binary_search(&test_binary_key) {
assert!(v[idx] == test_binary_key);
}else{
assert!(false);
}
});
}