C++ 标准库二分查找算法std::lower_bound
std::prev是C++标准库中的迭代器操作函数,用于获取双向或随机访问迭代器的前驱位置。主要特点包括:返回输入迭代器前n个位置的迭代器(默认n=1);适用于双向迭代器(如list)和随机访问迭代器(如vector);随机访问时效率为O(1),双向迭代需O(n)步骤。使用时需注意迭代器类型限制和越界风险,典型应用包括获取容器末尾元素(如std::prev(v.end()))或在循环中安全访问前驱
·
std::lower_bound 是 C++ 标准库中用于在有序序列中查找元素的重要函数,位于 <algorithm> 头文件中。它通过二分查找高效定位目标值的插入位置,适用于已排序的容器(如 vector、array 等)。以下是详细解析:
函数原型与参数
// 版本1:使用<运算符比较
template<class ForwardIt, class T>
ForwardIt lower_bound(ForwardIt first, ForwardIt last, const T& value);
// 版本2:使用自定义比较函数comp
template<class ForwardIt, class T, class Compare>
ForwardIt lower_bound(ForwardIt first, ForwardIt last, const T& value, Compare comp);
- 参数说明:
first, last:指向有序序列的迭代器范围(左闭右开区间[first, last))。value:要查找的目标值。comp(可选):自定义比较函数,需满足comp(a, b)为真时表示a应排在b前面。
功能与返回值
- 功能:在有序序列中查找第一个 不小于
value的元素位置。 - 返回值:迭代器指向满足
value <= *it的第一个元素;若所有元素都小于value,则返回last。
使用场景与示例
1. 基础用法(升序序列)
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> nums = {1, 3, 5, 7, 9, 11};
int target = 6;
auto it = std::lower_bound(nums.begin(), nums.end(), target);
if (it != nums.end()) {
std::cout << "第一个不小于 " << target << " 的元素是 " << *it << std::endl;
std::cout << "索引位置:" << (it - nums.begin()) << std::endl;
} else {
std::cout << "未找到" << std::endl;
}
// 输出:第一个不小于 6 的元素是 7,索引位置:3
}
2. 降序序列与自定义比较
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> nums = {11, 9, 7, 5, 3, 1}; // 降序排列
int target = 6;
// 使用自定义比较函数(降序时需反转比较逻辑)
auto it = std::lower_bound(nums.begin(), nums.end(), target,
[](int a, int b) { return a > b; });
if (it != nums.end()) {
std::cout << "降序中第一个不小于 " << target << " 的元素是 " << *it << std::endl;
}
// 输出:降序中第一个不小于 6 的元素是 7
}
3. 结构体与自定义类型
#include <iostream>
#include <vector>
#include <algorithm>
struct Person {
std::string name;
int age;
Person(std::string n, int a) : name(n), age(a) {}
};
// 自定义比较:按年龄升序
bool compareAge(const Person& p1, const Person& p2) {
return p1.age < p2.age;
}
int main() {
std::vector<Person> people = {
{"Alice", 25}, {"Bob", 30}, {"Charlie", 28}, {"David", 35}
};
Person target("", 28); // 查找年龄不小于28的第一个人
auto it = std::lower_bound(people.begin(), people.end(), target, compareAge);
if (it != people.end()) {
std::cout << "第一个年龄不小于28的人:" << it->name << ",年龄:" << it->age << std::endl;
}
// 输出:第一个年龄不小于28的人:Charlie,年龄:28
}
与其他查找函数的对比
| 函数 | 功能描述 | 时间复杂度 |
|---|---|---|
std::lower_bound |
查找第一个 不小于 value 的元素 |
O(log n) |
std::upper_bound |
查找第一个 大于 value 的元素 |
O(log n) |
std::equal_range |
返回 [lower_bound, upper_bound) 的迭代器对 |
O(log n) |
std::find |
线性查找等于 value 的元素(适用于无序序列) |
O(n) |
注意事项
- 序列必须有序:若输入序列未排序,
lower_bound的行为未定义。 - 迭代器要求:至少为前向迭代器(ForwardIt),但随机访问迭代器(如
vector::iterator)能优化二分查找的性能。 - 返回值含义:
- 若
value存在,lower_bound返回其首次出现的位置; - 若
value不存在,返回其应插入的位置(保持序列有序)。
- 若
- 自定义比较的一致性:使用
comp时,需确保比较逻辑与容器排序规则一致(如降序序列需传递反转的比较函数)。
典型应用
- 插入位置计算:在有序容器中插入元素时,用
lower_bound确定插入点以保持有序性:nums.insert(std::lower_bound(nums.begin(), nums.end(), 6), 6); - 二分查找变种:如查找第一个大于等于目标值的元素、统计不小于目标值的元素数量等。
- 高效去重:配合
unique函数,先排序再用lower_bound过滤重复元素。
通过合理使用 std::lower_bound,可在有序序列中实现高效的查找与插入操作,避免线性遍历的性能损耗。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐

所有评论(0)