C++ STL: lower_bound 和 upper_bound 的用法及区别

2025-01-31 13:00

在 C++ 标准模板库(STL)中,std::lower_boundstd::upper_bound 是两个强大的二分查找函数,适用于 有序范围(如 std::vectorstd::setstd::map)。这两个函数可以帮助我们快速找到元素的位置,支持高效的插入、统计和查找操作。

lower_boundupper_bound 的区别

std::lower_bound

  • 作用: 返回第一个 大于等于 (>=) 指定值的元素的迭代器。
  • 如果值存在: 返回该值的第一个位置。
  • 如果值不存在: 返回比目标值 大的第一个元素 位置。
  • 如果所有元素都小于目标值: 返回 end() 迭代器。
  • 反向查找小于目标值的元素: std::lower_bound 返回的迭代器减一,即 std::lower_bound(vec.begin(), vec.end(), target) - 1

std::upper_bound

  • 作用: 返回第一个 大于 (>) 指定值的元素的迭代器。
  • 如果值存在: 跳过所有相同值,返回比目标值 大的第一个元素 位置。
  • 如果值不存在: 返回比目标值 大的第一个元素 位置。
  • 如果所有元素都小于等于目标值: 返回 end() 迭代器。
  • 反向查找小于等于目标值的元素: std::upper_bound 返回的迭代器减一,即 std::upper_bound(vec.begin(), vec.end(), target) - 1

示例代码

虽然标准库只提供了“大于”和“大于等于”的函数,但是用这两个函数,可以组合出“小于”,“小于等于”和“等于”的判定。

#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> vec = {1, 2, 4, 4, 4, 6, 8, 10};
int target = 4;
// lower_bound
auto lower = std::lower_bound(vec.begin(), vec.end(), target);
std::cout << "lower_bound of " << target << " is at index: " << (lower - vec.begin()) << std::endl;
// upper_bound
auto upper = std::upper_bound(vec.begin(), vec.end(), target);
std::cout << "upper_bound of " << target << " is at index: " << (upper - vec.begin()) << std::endl;
// 找到最后一个小于 target 的元素
if (lower != vec.begin()) {
auto last_less = lower - 1;
std::cout << "Last element less than " << target << " is " << *last_less << " at index " << (last_less - vec.begin()) << std::endl;
} else {
std::cout << "No element is less than " << target << std::endl;
}
// 找到最后一个小于等于 target 的元素
if (upper != vec.begin()) {
auto last_less_equal = upper - 1;
std::cout << "Last element less than or equal to " << target << " is " << *last_less_equal << " at index " << (last_less_equal - vec.begin()) << std::endl;
} else {
std::cout << "No element is less than or equal to " << target << std::endl;
}
return 0;
}

运行结果

lower_bound of 4 is at index: 2
upper_bound of 4 is at index: 5
Last element less than 4 is 2 at index 1
Last element less than or equal to 4 is 4 at index 4

示例和拓展

1. 查找元素是否存在

if (lower != vec.end() && *lower == target) {
std::cout << target << " exists in the array at index " << (lower - vec.begin()) << std::endl;
} else {
std::cout << target << " does not exist in the array." << std::endl;
}

2. 统计目标值出现次数

int count = upper - lower;
std::cout << "Count of " << target << " is: " << count << std::endl;

3. 查找最后一个小于目标值的元素

if (lower != vec.begin()) {
auto last_less = lower - 1;
std::cout << "Last element less than " << target << " is " << *last_less << std::endl;
}

4. 查找最后一个小于等于目标值的元素

if (upper != vec.begin()) {
auto last_less_equal = upper - 1;
std::cout << "Last element less than or equal to " << target << " is " << *last_less_equal << std::endl;
}

复杂度分析

  • std::lower_boundstd::upper_bound 都基于二分查找,时间复杂度为 O(log n)
  • 适用于 有序序列,如果无序,则需要先排序 O(n log n),然后查找 O(log n)

总结

函数 返回 若值存在 若值不存在 典型应用
lower_bound 第一个 >= target 的迭代器 目标值的第一个位置 第一个比它大的元素 查找元素、插入位置
upper_bound 第一个 > target 的迭代器 跳过所有相同值的元素 第一个比它大的元素 计算元素出现次数
lower_bound - 1 最后一个 < target 的迭代器 目标值前一个元素 最大的小于 target 的元素 反向查找小于目标值
upper_bound - 1 最后一个 <= target 的迭代器 目标值最后一个位置 最大的小于等于 target 的元素 反向查找小于等于目标值
DeepSeek “源神”启动!「GitHub 热点速览」 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章 C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程) DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求 2 本地部署DeepSeek模型构建本地知识库+联网搜索详细步骤
点击右上角即可分享
微信分享提示