当前位置: 首页 > news >正文

C++ STL常用二分查找算法

lower_bound

lower_bound 是 C++ 标准库算法,通常用于有序序列中查找第一个不小于给定值的元素。它属于 <algorithm> 头文件,并且是基于二分查找实现的,因此要求输入序列必须是有序的。

基本语法

#include <algorithm>  // 引入算法库Iterator lower_bound(Iterator first, Iterator last, const T& value);
  • firstlast 是迭代器,分别表示容器的起始位置和结束位置(不包括 last)。

  • value 是要在容器中查找的目标值。

  • 返回值是迭代器,指向第一个不小于 value 的元素。如果没有找到符合条件的元素,返回 last

使用条件

  • 容器中的元素必须是有序的,通常是按非递减顺序(从小到大)排列的。

  • 如果容器无序,需要先对容器进行排序,才能使用 lower_bound

返回值解释

  • 如果找到一个元素,其值不小于 value,返回指向该元素的迭代器。

  • 如果所有元素都小于 value,返回 last,即容器的末尾。

示例代码

示例 1:简单查找
#include <iostream>
#include <vector>
#include <algorithm>  // 需要引入algorithmint main() {std::vector<int> v = {1, 2, 4, 4, 5, 8, 10};int value = 4;auto it = std::lower_bound(v.begin(), v.end(), value);if (it != v.end()) {std::cout << "第一个不小于 " << value << " 的元素是: " << *it << std::endl;} else {std::cout << "没有找到不小于 " << value << " 的元素。" << std::endl;}return 0;
}

输出

第一个不小于 4 的元素是: 4

在这个例子中,lower_bound 返回了指向值为 4 的第一个元素的迭代器。

示例 2:未找到的情况
#include <iostream>
#include <vector>
#include <algorithm>int main() {std::vector<int> v = {1, 2, 4, 4, 5, 8, 10};int value = 12;auto it = std::lower_bound(v.begin(), v.end(), value);if (it != v.end()) {std::cout << "第一个不小于 " << value << " 的元素是: " << *it << std::endl;} else {std::cout << "没有找到不小于 " << value << " 的元素。" << std::endl;}return 0;
}

输出

没有找到不小于 12 的元素。

因为所有元素都小于 12,所以返回 v.end()

注意事项

  1. 容器必须有序:如果容器未排序,lower_bound 的结果是未定义的。

  2. 时间复杂度:由于使用二分查找,时间复杂度为 O(logn),其中 n 是容器中元素的数量。

  3. 自定义比较函数:如果需要使用自定义的顺序规则,可以提供一个比较函数作为参数,例如

    auto it = std::lower_bound(v.begin(), v.end(), value, custom_compare);

    其中 custom_compare 是一个函数对象,接收两个元素作为参数,返回一个布尔值,用于定义排序规则。

lower_bound 是一个非常实用的函数,特别适合在有序数据中进行高效的查找操作。

upper_bound

upper_bound 是 C++ 标准库中的一个算法函数,与 lower_bound 类似,它也用于有序序列中查找特定值的位置,但功能略有不同。upper_bound 用于查找第一个大于给定值的元素的位置。它同样基于二分查找实现,因此要求输入序列必须是有序的。

基本语法

#include <algorithm>  // 引入算法库Iterator upper_bound(Iterator first, Iterator last, const T& value);
  • firstlast 是迭代器,分别表示容器的起始位置和结束位置(不包括 last)。

  • value 是要在容器中查找的目标值。

  • 返回值是迭代器,指向第一个大于 value 的元素。如果没有找到符合条件的元素,返回 last

使用条件

  • 容器中的元素必须是有序的,通常是按非递减顺序(从小到大)排列的。

  • 如果容器无序,需要先对容器进行排序,才能使用 upper_bound

返回值解释

  • 如果找到一个元素,其值大于 value,返回指向该元素的迭代器。

  • 如果所有元素都小于或等于 value,返回 last,即容器的末尾。

示例代码

示例 1:简单查找
#include <iostream>
#include <vector>
#include <algorithm>  // 需要引入algorithmint main() {std::vector<int> v = {1, 2, 4, 4, 5, 8, 10};int value = 4;auto it = std::upper_bound(v.begin(), v.end(), value);if (it != v.end()) {std::cout << "第一个大于 " << value << " 的元素是: " << *it << std::endl;} else {std::cout << "没有找到大于 " << value << " 的元素。" << std::endl;}return 0;
}

输出

第一个大于 4 的元素是: 5

在这个例子中,upper_bound 返回了指向值为 5 的元素的迭代器。

示例 2:未找到的情况
#include <iostream>
#include <vector>
#include <algorithm>int main() {std::vector<int> v = {1, 2, 4, 4, 5, 8, 10};int value = 12;auto it = std::upper_bound(v.begin(), v.end(), value);if (it != v.end()) {std::cout << "第一个大于 " << value << " 的元素是: " << *it << std::endl;} else {std::cout << "没有找到大于 " << value << " 的元素。" << std::endl;}return 0;
}

输出

没有找到大于 12 的元素。

因为所有元素都小于或等于 12,所以返回 v.end()

注意事项

  1. 容器必须有序:如果容器未排序,upper_bound 的结果是未定义的。

  2. 时间复杂度:由于使用二分查找,时间复杂度为 O(logn),其中 n 是容器中元素的数量。

  3. 自定义比较函数:如果需要使用自定义的顺序规则,可以提供一个比较函数作为参数,例如

    auto it = std::upper_bound(v.begin(), v.end(), value, custom_compare);

    其中 custom_compare 是一个函数对象,接收两个元素作为参数,返回一个布尔值,用于定义排序规则。

  4. lower_bound 的区别

    • lower_bound 返回第一个不小于给定值的元素。

    • upper_bound 返回第一个大于给定值的元素。

    • 如果容器中存在多个相同的值,lower_bound 会返回第一个等于该值的元素,而 upper_bound 会返回第一个大于该值的元素。

应用场景

upper_bound 常用于以下场景:

  • 在有序序列中查找第一个大于某个值的元素。

  • 用于实现区间查找,例如结合 lower_boundupper_bound 来查找某个值的范围。

http://www.xdnf.cn/news/1053685.html

相关文章:

  • 2025年品牌定位推荐排行榜:锚定市场航向,解锁品牌增长新势能
  • Python+QT远程控制助手-ver2
  • 《注解的江湖:一场元数据的“宫斗剧”》
  • 每日算法刷题Day32 6.15:leetcode枚举技巧7道题,用时1h10min
  • 计网复习知识(17)应用层
  • jQuery 3D透明蓄水池状柱状图插件
  • IDA动态调试环境配置全流程
  • 【Markdown】基础用法汇总(标题、列表、链接、图片、加粗斜体、上下角标、引用块、代码块、公式)
  • 学习日记-day30-6.15
  • Linux安装LLaMA Factory
  • Netty 全面深入学习指南
  • 项目实训个人工作梳理
  • 【算法 day03】LeetCode 203.移除链表元素 | 707.设计链表 | 206.反转链表
  • nodejs中Express框架的基本使用
  • ​​信息系统项目管理师-项目范围管理 知识点总结与例题分析​​
  • Claude Code 实用教程——使用方法详解
  • 庙算兵棋推演AI开发初探(8-神经网络模型接智能体进行游戏)
  • 文本预测和分类任务
  • [笔记] 基于esp32s3用GUI-Guider-1.9.1-GA开发LVGL界面
  • 认识电子元器件之磁传感器
  • Spring有代理对象的循环依赖时,如何确保代理对象能够正确持有原始对象的所有属性赋值结果?
  • 234. 回文链表
  • SQL 增删改查 —— 笔记篇
  • 面向对象设计原则
  • 深度学习——基于卷积神经网络实现食物图像分类【3】(保存最优模型)
  • React19源码系列之Hooks(useState)
  • Linux中的连接符
  • 谐波减速器 MINIF8 和 MINIF11 的区别
  • 事务传播机制分析:用户注册场景分析
  • 日语学习-日语知识点小记-进阶-JLPT-真题训练-N2阶段(2):2020年12月2018年7月