C++ upper_bound()和lower_bound()(二分查找中使用)的定义,使用方法和区别

这篇具有很好参考价值的文章主要介绍了C++ upper_bound()和lower_bound()(二分查找中使用)的定义,使用方法和区别。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

C++ upper_bound()和lower_bound()是涉及二分查找问题一个很好用的工具,熟练使用就不用为二分查找的边界发愁了(不用重复造轮子了)

1. 调用方式

upper_bound有两种调用方式:

template <class ForwardIterator, class T>  
ForwardIterator upper_bound (ForwardIterator first, ForwardIterator last, const T& val);
template <class ForwardIterator, class T, class Compare>  
ForwardIterator upper_bound (ForwardIterator first, ForwardIterator last, const T& val, Compare comp);

注意:

  1. 前两个参数是ForwardIterator 类型(这个一般比较容易满足,各种RandomAccessIterator都满足,而最常见的对vector排序,vector的迭代器就是RandomAccessIterator,参见:各种iterator之间的关系
  2. 如果采用自定义比较函数,传入的是对象而不是类名!!这个和构建一些有序的数据结构,如priority_queue,map,set等不一样,一般这些传入的是类名而不是一个对象!(举个例子,sort中的comp可以传入greater(),而不能是greater,见下文),其中涉及到函数对象的知识,可以参考:C++ 函数对象(Function Object)是什么?
    而对于构建priority_queue,这里传入的就是类名,而不是一个对象!
template<
    class T,
    class Container = std::vector<T>,
    class Compare = std::less<typename Container::value_type>
> class priority_queue;

同样的对于lower_bound来说也是如此:

template <class ForwardIterator, class T>  
ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last, const T& val);
template <class ForwardIterator, class T, class Compare>  
ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last, const T& val, Compare comp);

2. upper_bound()和lower_bound()定义和区别

定义

文档中的关于upper_bound()和lower_bound()的介绍值得深入细读:
以下来自官方文档:
upper_bound()

  1. 返回指向范围[first,last)中第一个元素使得value < element(或comp(value,element))为true(即严格大的迭代器),如果找不到这样的元素,则为last。
  2. [first,last)必须根据表达式!(value < element)或!comp(value,element)进行分区,即表达式为true的所有元素必须在表达式为false的所有元素之前!完全排序的[first,last)符合此条件。
  3. 如果没有自定义比较函数就使用operator<来比较element,如果自定义了比较函数就使用comp来比较element

lower_bound()

  1. 返回指向范围[first,last)中的第一个元素使得该元素不满足element< value(或comp(element,value)为false)、(即大于或等于)的迭代器,如果找不到这样的元素,则返回last。

  2. [first,last)必须相对于表达式element< value(或comp(element,value))进行分区,即表达式为true的所有元素必须在表达式为false的所有元素之前。完全排序的[first,last)符合此条件。

  3. 如果没有自定义比较函数就使用operator<来比较element,如果自定义了比较函数就使用comp来比较element

2.1 lower_bound:

Returns an iterator pointing to the first element in the range [first, last) that does not satisfy element < value (or comp(element, value)), (i.e. greater or equal to), or last if no such element is found.

这里的value就是模板里的val,element就是要比较的元素

注意:在C++比较过程中,A less than B(A < B),表示按照“从小到大”(可以自定义)排序的话,A应该放在B前面
所以这里does not compare less than val就是greater或者equal to val的含义,也就是lower_bound返回 [first, last) 第一个不满足element < value(或者不满足comp(element, value))的元素的iterator,如果都不满足,则返回last这个iterator

注意:
1.

The range [first, last) must be partitioned with respect to the expression element < value (or comp(element, value)), i.e., all elements for which the expression is true must precede all elements for which the expression is false. A fully-sorted range meets this criterion.

也就是如果从大到小排序(greater),但是却用从小到大中以及最大的值作为比较函数,是查不到第一个元素的,而是返回last。
举例如下:

vector<int> vec = {1, 2, 3, 4, 5, 6};
// 从大到小排序
// greater必须加上()因为需要传入一个对象
sort(vec.begin(), vec.end(), greater<int>()); 
// 以默认的从小到大作为比较函数以及最大的值(此为6)作为value
auto iter = lower_bound(vec.begin(), vec.end(), 6);

这里返回的iter就是vec.end(),因为所有没有任何元素满足element < 6。
2. comp(element, value),第二个参数才是value!!

举例:对于自定义比较函数:

#include <iostream>     // std::cout
#include <algorithm>    // std::lower_bound
#include <vector>       // std::vector
using namespace std;
//以普通函数的方式定义查找规则
bool mycomp(int i,int j) { return i>j; }

//以函数对象的形式定义查找规则
class mycomp2 {
public:
    bool operator()(const int& i, const int& j) {
        return i > j;
    }
};

int main() {
    int a[5] = { 1,2,3,4,5 };
    //从 a 数组中找到第一个不小于 3 的元素
    int *p = lower_bound(a, a + 5, 3);
    cout << "*p = " << *p << endl;

    vector<int> myvector{ 4,8, 9, 5,3,1,7, 2 };
    //根据 mycomp2 规则,从 myvector 容器中找到第一个违背 mycomp2 规则的元素
    vector<int>::iterator iter = lower_bound(myvector.begin(), myvector.end(),3,mycomp2());
    cout << "*iter = " << *iter;
    return 0;
}

输出的结果:

*p = 3
*iter = 3

在第二个例子中,3前面所有的元素都是大于3的,后面所有的元素都是小于3

2.2 upper_bound()

注意要点:

  1. comp(value,element),第一个参数就是value!!
    举例如下:
#include <iostream>     // std::cout
#include <algorithm>    // std::upper_bound
#include <vector>       // std::vector
using namespace std;
//以普通函数的方式定义查找规则
bool mycomp(int i, int j) { return i > j; }
//以函数对象的形式定义查找规则
class mycomp2 {
public:
    bool operator()(const int& i, const int& j) {
        return i > j;
    }
};
int main() {
    int a[5] = { 1,2,3,4,5 };
    //从 a 数组中找到第一个大于 3 的元素
    int *p = upper_bound(a, a + 5, 3);
    cout << "*p = " << *p << endl;
    vector<int> myvector{ 4,5,3,1,2 };
    //根据 mycomp2 规则,从 myvector 容器中找到第一个违背 mycomp2 规则的元素
    vector<int>::iterator iter = upper_bound(myvector.begin(), myvector.end(), 3, mycomp2());
    cout << "*iter = " << *iter;
    return 0;
}

输出:

*p = 4
*iter = 1

在实际情况中,我们遇到的最多的就是给定从小到大排序好的数组,找出第一个大于某个元素或者大于等于某个元素的位置,找出第一个大于某个元素的位置就是用的upper_bound(),找出大于等于某个元素的位置就是lower_bound(),更复杂的情况就需要借助自定义的比较函数了。文章来源地址https://www.toymoban.com/news/detail-678349.html

参考资料:

  1. https://en.cppreference.com/w/cpp/algorithm/upper_bound
  2. https://en.cppreference.com/w/cpp/algorithm/lower_bound
  3. 代码案例部分来自于C语言中文网

到了这里,关于C++ upper_bound()和lower_bound()(二分查找中使用)的定义,使用方法和区别的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 问题 C: 二分查找右侧边界(C++)(二分查找)

    1.题目描述 2.AC 问题 C: 二分查找右侧边界 时间限制: 1.000 Sec  内存限制: 128 MB 提交 状态 题目描述 请在一个有序不递减的数组中(数组中的值有相等的值),采用二分查找,找到最后1次出现值x的位置,如果不存在x请输出-1。 请注意:本题要求出q个x,每个x在数组中第一

    2024年02月03日
    浏览(45)
  • C++二分算法(二分查找&二分答案)细节详解

     二分算法可以分为 二分查找 和 二分答案 。 以在一个 升序数组 中查找一个数为例。它每次考察数组当前部分的 中间元素 ,如果中间元素刚好是要找的,就结束搜索过程;如果中间元素小于所查找的值,那么左侧的只会更小,不会有所查找的元素,只需到右侧查找;如果

    2024年02月08日
    浏览(53)
  • 二分查找算法讲解及其C++代码实现

    二分查找算法是一种常用的查找算法,也被称为折半查找。它可以在有序的数组或列表中快速查找需要的元素。 算法描述: 首先确定数组的中间位置mid=(left+right)/2; 然后将要查找的值key与中间位置的值进行比较; 如果key等于中间位置的值,则查找成功,返回mid; 如果key小

    2024年02月01日
    浏览(44)
  • C++二分查找算法:132 模式枚举3

    本篇是视频课程的讲义,可以看直接查看视频。也可以下载源码,包括空源码。 二分查找算法合集 包括题目及代码 C++二分查找算法:132 模式解法一枚举3 C++二分查找算法:132 模式解法二枚举2 代码最简洁 C++二分查找算法:132 模式解法三枚举1 性能最佳 C++单调向量算法:1

    2024年02月04日
    浏览(41)
  • 二分查找的两种形式(C++实现)

    现在有一个这样的问题需要求解 题目要求:给定一个n个元素的(升序)整型数组nums和一个目标值target,写一个函数搜索nums中的target,如果目标值存在返回下标,否则返回-1 示例 继上次写完二分查找后,又在网上查看了其他资料,发现二分查找其实常用的有两种写法,这篇

    2024年02月03日
    浏览(56)
  • C++二分查找算法:132 模式解法二枚举2

    二分查找算法合集 包括题目及代码 C++二分查找算法:132 模式解法一枚举3 C++二分查找算法:132 模式解法二枚举2 代码简洁 C++二分查找算法:132 模式解法三枚举1 性能最佳 C++单调向量算法:132 模式解法三枚举1 代码更简洁 C++二分查找算法:132模式枚举3简洁版 代码简洁,性能

    2024年02月05日
    浏览(46)
  • C++二分查找算法的应用:最长递增子序列

    C++二分算法应用:最长递增子序列 二分查找算法合集 单调映射 点击下载源码 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子

    2024年02月06日
    浏览(44)
  • 【动态规划】【二分查找】C++算法 466 统计重复个数

    视频算法专题 动态规划汇总 二分查找 定义 str = [s, n] 表示 str 由 n 个字符串 s 连接构成。 例如,str == [“abc”, 3] ==“abcabcabc” 。 如果可以从 s2 中删除某些字符使其变为 s1,则称字符串 s1 可以从字符串 s2 获得。 例如,根据定义,s1 = “abc” 可以从 s2 = “abdbec” 获得,仅需

    2024年01月23日
    浏览(50)
  • 【动态规划】【二分查找】【C++算法】730. 统计不同回文子序列

    视频算法专题 动态规划汇总 二分查找算法合集 给你一个字符串 s ,返回 s 中不同的非空回文子序列个数 。由于答案可能很大,请返回对 109 + 7 取余 的结果。 字符串的子序列可以经由字符串删除 0 个或多个字符获得。 如果一个序列与它反转后的序列一致,那么它是回文序列

    2024年01月19日
    浏览(50)
  • C++二分查找算法:有序矩阵中的第 k 个最小数组和

    二分查找算法合集 C++二分查找算法:查找和最小的 K 对数字 十分接近m恒等于2 给你一个 m * n 的矩阵 mat,以及一个整数 k ,矩阵中的每一行都以非递减的顺序排列。 你可以从每一行中选出 1 个元素形成一个数组。返回所有可能数组中的第 k 个 最小 数组和。 示例 1: 输入:

    2024年02月05日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包