1.二分查找的前提
-
只有单调的序列才能进行二分查找;
-
一般为单调不减,单调不增需要像 sort() 一样修改比较函数;
2.binary_search( ) 函数
-
binary_search( ) 是算法库(algorithm)函数里面的,用于在一个已经排好序的序列(数组或者容器)中查找目标值target;
-
底层实现为进行二分查找,函数返回一个 bool 值来表示目标值 target 是否存在于此序列中
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> a = {1,2,4,7,8,9,12};
int target = 8;
bool retult = binary_search(a.begin(),a.end(),target); //前两个参数为查找范围始终点,第三个参数为target;
if(retult) cout << "yes";
else cout << "no";
return 0;
}
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int a[10] = {1,2,4,7,8,9,12};
int target = 8;
bool retult = binary_search(a,a+7,target); //迭代器可以,数组地址也可以
if(retult) cout << "yes";
else cout << "no";
return 0;
}
3.lower_bound( ) 和 upper_bound( )函数
1)lower_bound( )
-
是在非降序序列中寻找 target 值的所在地址;
-
lower_bound(a,b,target)会返回此序列 [a,b) 中第一个大于等于 target 值的地址;
-
想获得其下标需要使用其返回值减去a的地址,即 a.begin() 或者 a ;
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int a[10] = {1,3,2,11,8,9,10};
int target = 8;
sort(a,a+7);
cout << "target第一次出现在:" << lower_bound(a,a+7,target)-a;
return 0;
}
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> a = {1,3,2,11,8,9,10};
int target = 8;
sort(a.begin(),a.end());
cout << "target第一次出现在:" << lower_bound(a.begin(),a.end(),target)-a.begin();
return 0;
}
2)upper_bound( )
-
与 lower_bound( ) 相同,都是在非降序序列;
-
upper_bound(a,b,target) 返回此序列 [a,b) 中第一个大于 target 值的地址;
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> a = {1,3,2,11,8,8,8,8,8,9,10};
int target = 8;
sort(a.begin(),a.end());
cout << upper_bound(a.begin(),a.end(),target)-a.begin();
return 0;
}
3)总结
-
当一个序列中存在多个 target 值时,lower_bound( ) 所得到的是序列中第一个 target 值所在的下标a,upper_bound( ) 所得到的是序列中第一个大于 target 值所在的下标b,故此此序列下标 [a,b) 的所有数据均为 target ;