0


C++ 手写实现类似lower_bound和upper_bound的二分功能

目录

lower_bound和upper_bound介绍

lower_bound函数的作用是查找范围内第一个大于等于目标元素的元素迭代器/指针

数组的简单使用:

  1. int num[5]={1,3,5,7,9};
  2. int *pos=lower_bound(num,num+5,key);
  1. int num[5]={1,3,5,7,9}
  2. int pos=lower_bound(num,num+5,key)-num;

vector容器的简单使用:

  1. vector<int> ve{1,3,5,7,9}
  2. vector<int>::iterator pos=lower_bound(ve.begin(),ve.end(),key);
  1. vector<int> ve{1,3,5,7,9}
  2. auto pos=lower_bound(ve.begin(),ve.end(),key)-ve.begin();

upper_bound的作用是查找范围内第一个大于目标元素的元素迭代器/指针
使用方法和lower_bound相同

手动实现类似的二分效果

lower_bound函数是查找范围内第一个大于等于
upper_bound函数是查找范围内第一个大于
并且如果范围内没有符合条件的值,就返回范围内最后一个元素的下一个迭代器/指针

接下来将写两个简单的二分函数,实现二分查找目标范围内第一个大于等于/大于的值,如果找不到范围内最后一个元素的下一个元素的位置.

lower_bound

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int lower_bound(int a[],int left,int right,int key)
  4. {
  5. while(left<=right)
  6. {
  7. int mid=(left+right)>>1;
  8. if(a[mid]>=key)
  9. {
  10. right=mid-1;
  11. }
  12. else
  13. left=mid+1;
  14. }
  15. return left;
  16. }
  17. int main()
  18. {
  19. int a[5]={1,3,5,7,9};
  20. cout<< lower_bound(a,0,4,6) <<endl;
  21. cout<< lower_bound(a,0,4,100)<<endl;
  22. }

upper_bound

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int upper_bound(int a[],int left,int right,int key)
  4. {
  5. while(left<=right)
  6. {
  7. int mid=(left+right)>>1;
  8. if(a[mid]>key)
  9. {
  10. right=mid-1;
  11. }
  12. else
  13. left=mid+1;
  14. }
  15. return left;
  16. }
  17. int main()
  18. {
  19. int a[5]={1,3,5,7,9};
  20. cout<< upper_bound(a,0,4,6) <<endl;
  21. cout<< upper_bound(a,0,4,100)<<endl;
  22. }

另一种常见的二分形式

这样写也能实现二分的功能,但是没办法在找不到的情况下返回正确的值.

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int lower_bound(int a[],int left,int right,int key)
  4. {
  5. while(left<right)
  6. {
  7. int mid=(left+right)>>1;
  8. cout<<left<<" "<<right<<" "<<mid<<endl;
  9. if(a[mid]>=key)
  10. {
  11. right=mid;
  12. }
  13. else
  14. left=mid+1;
  15. }
  16. return left;
  17. }
  18. int main()
  19. {
  20. int a[5]={1,3,5,7,9};
  21. cout<< lower_bound(a,0,4,7) <<endl;
  22. }

对lower_bound函数使用lamda函数

lower_bound函数是实际是有四个参数的
在这里插入图片描述

最后一个参数是比较规则,我们可以在第四个参数的位置,放上函数指针自定义排序规则.

也可以放入lamda表达式
仔细看,lower_bound函数中的_Val也就是上文说的Key值,它会在运行过程中将自己的值传递给比较函数中的第二个参数.

代码:

  1. #include<iostream>
  2. #include<string>
  3. #include<vector>
  4. #include<algorithm>
  5. using namespace std;
  6. vector<int> ve{ -1,3,-5,-6,7 };
  7. int main()
  8. {
  9. std::sort(ve.begin(), ve.end());
  10. int pos = lower_bound(ve.begin(), ve.end(), 3, [](int a, int b) {
  11. cout << a << " " << b << endl;
  12. return a < b;
  13. }) - ve.begin();
  14. cout << pos << endl;
  15. }

我们可以打印a和b来观察二分过程中lamda表达式中参数的变化.发现参数b的值始终=_Val的值是不变的.

我们可以自定义二分的规则,但是前提是,二分的数组必须是有序的(升序或者降序)都行,并且比较的规则也需要是有单调性的.

我们也可以利用lamda函数对一个降序的数组,求数组中第一个小于等于目标元素的元素位置

代码:

  1. #include<iostream>
  2. #include<string>
  3. #include<vector>
  4. #include<algorithm>
  5. using namespace std;
  6. vector<int> ve{ -1,3,-5,-6,7 };
  7. int main()
  8. {
  9. std::sort(ve.begin(), ve.end(),[](int a,int b)
  10. {
  11. return a>b;
  12. });
  13. // 7 3 -1 -5 -6
  14. int pos=lower_bound(ve.begin(),ve.end(),-7,[](int a,int b){
  15. return a>b;
  16. })-ve.begin();
  17. cout<<pos<<endl;
  18. }
标签: c++ 算法

本文转载自: https://blog.csdn.net/qq_52508038/article/details/132584113
版权归原作者 WE xiye 所有, 如有侵权,请联系我们删除。

“C++ 手写实现类似lower_bound和upper_bound的二分功能”的评论:

还没有评论