介绍C++库函数upper_bound和lower_bound

介绍C++库函数upper_bound和lower_bound

文章目录

  • 介绍C++库函数upper_bound和lower_bound
    • 前言
    • 具体介绍
      • upper_bound
      • lower_bound
    • 总结:
    • 结束了

前言

  • 这两个库函数是用二分的方法查找元素
  • 时间复杂度是 O ( l o g n ) O(logn) O(logn) 级别
  • 在头文件内
  • 注意 因为是二分,所以一定是满足单调性的,不然使用这两个函数没有什么意义

具体介绍

upper_bound

第一个函数声明

template<typename _ForwardIterator, typename _Tp>
    inline _ForwardIterator
    upper_bound(_ForwardIterator __first, _ForwardIterator __last,
		const _Tp& __val)
  • _ForwardIterator是迭代器类型,可以是指针
  • _Tp是元素类型,例如 int double, 也可以是自定义类型
  • 第一个和第二个参数表示要搜索的起始位置__first和终止位置__last, 第三个是要搜索的元素__val
  • 返回值也是一个迭代器类型, 返回的是能在不改变顺序的条件的把这个元素__val插到这段区间的最后一个位置, 也就是严格大于这个元素的第一个位置,如果不存在这样的数字,那么就返回end()

简单示例:

#include 
#include 

int main()
{
    int arr[] = {1, 2, 2, 4, 4, 5, 6, 7, 8};
    int len = sizeof arr / sizeof arr[0];
    auto t = std::upper_bound(arr, arr + len, 4);
    std::cout << *t << std::endl;
    std::cout << "index = " << t - arr << std::endl;
    return 0;
}

执行结果:

5
index = 5

  • 首先第一个输出的是要把4插入不改变顺序的位置的元素
  • 注意 是最后一个位置,所以第二个结果是index = 5, 是能把这个元素插进去不改变顺序的最后一个位置, 同时也是大于4的第一个位置

当然我们也可以指定搜索的规则,就有了如下的函数重载

第二个函数声明

template<typename _ForwardIterator, typename _Tp, typename _Compare>
    inline _ForwardIterator
    upper_bound(_ForwardIterator __first, _ForwardIterator __last,
		const _Tp& __val, _Compare __comp)
  • 额外加的参数是一个可调用对象_Compare类型,可以是**lambda表达式**, 函数, 谓词
  • 这个参数可以让函数根据我们自己定义的规则来进行比较查找

简单示例:

上面的例子的upper_bound和下面的的是一样的
auto t = std::upper_bound(arr, arr + len, 4, [&](int x, const int& val){
        return x < val;
    });
  • 可调用对象:第一个参数是要搜的元素, 就上面的例子而言,x就是4, 第二个参数是迭代的区间的一个单位,上面的例子就是int, 所以加上不可修改就改成了const int&, 如果arr的类型是std::vector>那么第二个参数就可以是const vector&, 当然也可以用 const auto&,但是原则是使用者本身知道auto代指的是什么类型,注意:两个参数的位置不能交换,否则会产生错误
  • 比较规则:返回的是满足规则的第一个元素的位置,例如return x < val;表示的就是数组中的元素val大于x第一个位置, 如果改成return x <= val;那么表示的意思就是第一个满足这个的条件的第一个位置,此时程序运行的结果是4, index = 3

lower_bound

此函数和upper_bound函数是类似的,用法基本一致

第一个函数声明

template<typename _ForwardIterator, typename _Tp>
    inline _ForwardIterator
    lower_bound(_ForwardIterator __first, _ForwardIterator __last,
		const _Tp& __val)
  • 参数和upper_bound完全相同
  • 函数的功能是 找到能把这个元素插进去并且不改变这个顺序的第一个位置也就是返回的是第一个不小于__val的第一个位置,如果不存在这样的数,那么返回end()

第二个函数声明

template<typename _ForwardIterator, typename _Tp, typename _Compare>
    inline _ForwardIterator
    lower_bound(_ForwardIterator __first, _ForwardIterator __last,
		const _Tp& __val, _Compare __comp)
  • 要注意的一点是第一个参数是迭代的区间的一个单位, 第二个参数是要搜的元素,其他大部分和上面的基本相同,不多赘述

简单例子

vector<vector<int>> a;
// 初始化 a
auto t = lower_bound(a.begin(), a.end(), 1, [&](const vector<int>& val, int x)
        {
            return x > val[1];
        });

总结:

  • 这两个函数非常重要,以二分在 O ( l o g n ) O(logn) O(logn)的时间复杂度快速查找,算法中常用的函数
  • 多积累

结束了

你可能感兴趣的:(c++,算法,数据结构)