lower_bound()/upper_bound()函数(C++)

1.lower_bound()/upper_bound()函数简单介绍

 1.1 lower_bound() 用于二分查找区间内第一个 大于等于某值(>= x) 的迭代器位置
 1.2 upper_bound() 用于二分查找区间内第一个 大于某值(> x) 的迭代器位置


2.lower_bound()/upper_bound()函数分析

 2.1 函数参数分析
 ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last, const T& val)
 ForwardIterator upper_bound (ForwardIterator first, ForwardIterator last, const T& val)
 函数前两个参数分别是已被排序的序列的起始迭代器位置和结束迭代器位置,将要被查询的范围为[ first, last ),是一个左闭右开区间的范围,第三个参数则是需要搜寻的元素的值。最后返回查询成功的迭代器的位置。

 2.2 函数内部原理实现分析
 使用lower_bound()进行一个简单的介绍,其实可以发现这个函数底层实现的一个逻辑就是二分查找

  ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last, const T& val)
{
    
    
  ForwardIterator it;
  iterator_traits<ForwardIterator>::difference_type count, step;
  count = distance(first,last);
  while (count>0) // 底层逻辑就是二分查找
  {
    
    
    it = first; step=count/2; advance (it,step);  // 每次获取区间范围的一半
    if (*it<val) {
    
                     
      first=++it;
      count-=step+1;
    }
    else count=step;
  }
  return first;
}

 2.3 函数相关细节注意
 A. 搜索的序列必须是已经按照一定规则进行过排序的有序序列
 因为之前我们就介绍了这个函数是二分进行搜索位置的,所以必须保证其顺序必须是有序的才可以,否则会乱套的,之后也可以运行展示以下如果不是有序的序列会出现的错误。
 B. 搜索的序列本身必须可以传入迭代器参数
 因为这个函数需要传入的参数就是迭代器的位置,所以如果对于本身没有迭代器参数的序列是无法使用的,例如 queue容器是无法使用的(本身没有迭代器成员函数),对于一般数组,vector容器,deque容器,set容器等(本身有迭代器函数)都可以直接使用
 C. 搜索的序列当中若无合法答案返回 last 迭代器位置
 我们搜索的序列是[ fitst, last ],当其中没有我们想要的结果则会返回last迭代器的位置我们也可以借此确认是否真的可以成功搜索到合法结果。

 2.4: 函数头文件 algorithm库

3.lower_bound()/upper_bound()运行展示

 3.1 函数正常使用展示
  lower_bound() 找到第一个 >= x 的合法位置
  upper_bound() 找到第一个 > x 的合法位置

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
int main(){
    
    
    int a[7] = {
    
    0, 1, 3, 5, 8, 10, 16};
    for(int i = 0; i < 7; i ++ ) cout << a[i] << ' ';
    cout << "\n第一个 >= 3 元素的大小为:  元素位置为:  " << endl;
    cout << * lower_bound(a, a + 7, 3) << "\t";
    cout << lower_bound(a, a + 7, 3) - a << endl;
    cout << "第一个 > 3 元素的大小为:  元素位置为:  " << endl;
    cout << * upper_bound(a, a + 7, 3) << "\t";
    cout << upper_bound(a, a + 7, 3) - a << endl;
}

在这里插入图片描述

 3.2 函数细节1——搜索之前必须是有序序列
 我们设计一个没有排序的队列尝试一下,也可以看看其内部的搜索顺序是二分查找的一个顺序,我们可以看看结果。
  这个序列第一个二分查找的元素就是9,然后查找 2 不合法,然后 1 9 中会将9作为结果输出

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
int main(){
    
    
    int a[7] = {
    
    10, 2, 1, 9, 8, 2, 16};
    for(int i = 0; i < 7; i ++ ) cout << a[i] << ' ';
    cout << "\n第一个 >= 3 元素的大小为:  元素位置为:  " << endl;
    cout << * lower_bound(a, a + 7, 3) << "\t";
    cout << lower_bound(a, a + 7, 3) - a << endl;

}

在这里插入图片描述

 3.3 函数细节2——搜索对象必须是可以传入迭代器参数的序列
 没有迭代器成员函数的容器是无法使用的例如 queue , 其他迭代器都可以正常使用例如vector, set等
在这里插入图片描述 常用的一般就是 vector容器, 也可以用 vector容器和set容器, deque容器 等(提醒:set容器本身内部就是有序)
 vector容器

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long LL;
int main(){
    
    
    vector<int> v;
    v.push_back(4), v.push_back(8), v.push_back(1), v.push_back(2), v.push_back(6);
    sort(v.begin(), v.end());
    cout << "第一个 >= 3 的元素位置为: " << endl;
    cout << lower_bound(v.begin(), v.end(), 3) - v.begin() << endl;
    cout << "第一个 >= 3 的元素大小为: " << endl;
    cout << *lower_bound(v.begin(), v.end(), 3) << endl;
}

在这里插入图片描述
 set容器本身内部即有序(不需要排序操作)

#include<iostream>
#include<algorithm>
#include<set>
using namespace std;
typedef long long LL;
int main(){
    
    
    set<int> s;
    s.insert(4), s.insert(2), s.insert(1), s.insert(5), s.insert(3);
    set<int>::iterator it = s.begin();
    for(; it != s.end(); it ++ ){
    
    
        cout << * it << ' ';
    }
    cout << '\n';
    cout << "第一个 >= 2 的数字为" << endl;
    cout << * lower_bound(s.begin(), s.end(), 2) << endl;

}

在这里插入图片描述


 3.4 函数细节3——若无法搜索到合法答案返回末尾迭代器

#include<iostream>
#include<algorithm>
#include<set>
using namespace std;
typedef long long LL;
int main(){
    
    
    int a[4] = {
    
    1, 2, 3, 4};
    cout << "找到第一个 >= 5 的元素的大小" << endl;
    cout <<  * lower_bound(a, a + 4, 5) << endl;
    cout << "找到第一个 >= 5 的元素的相对位置" << endl;
    cout <<  lower_bound(a, a + 4, 5) - a << endl;
    if(lower_bound(a, a + 4, 5) == a + 4){
    
    
        cout << "没有正确的结果, 返回元素末尾[last]的位置" << endl;
    
}


在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_51566349/article/details/128086465