C++ upper_bound怎么用 C++查找第一个大于目标值元素的方法【STL】

8次阅读

upper_bound查找第一个严格大于目标值的元素位置,要求区间已排序,返回迭代器,若无满足元素则返回末尾迭代器;使用时需区分lower_bound,注意自定义比较函数的语义一致性,并通过it != container.end()判断是否找到。

C++ upper_bound怎么用 C++查找第一个大于目标值元素的方法【STL】

upper_bound 查找第一个大于目标值的元素位置

upper_bound 是 STL 中用于在**已排序区间**中查找第一个严格大于给定值的元素的函数。它不找“等于”,也不找“大于等于”,只认准“严格大于”。返回的是一个迭代器,指向该元素;如果所有元素都不满足条件,就返回末尾迭代器(如 v.end())。

常见错误是把它和 lower_bound 混用:比如想查“大于等于”,却用了 upper_bound,结果跳过相等元素直接往后找,导致逻辑偏移。

使用前必须确保容器/数组已升序排列,否则行为未定义——哪怕只错一个位置,upper_bound 也可能返回完全错误的迭代器。

vector 和普通数组上怎么调用 upper_bound

std::vector,直接传入 begin()end() 和目标值:

立即学习C++免费学习笔记(深入)”;

std::vector v = {1, 2, 2, 3, 4, 4, 5}; auto it = std::upper_bound(v.begin(), v.end(), 2); // 指向第1个3,即索引3

对原始数组,需手动传入指针

int arr[] = {1, 2, 2, 3, 4, 4, 5}; int n = sizeof(arr) / sizeof(arr[0]); auto ptr = std::upper_bound(arr, arr + n, 4); // 指向5,即 arr + 6
  • 第三个参数是值本身,不是引用或指针
  • 返回类型始终是输入迭代器类型(vector::iteratorint*),别用 auto 后误当成 int
  • 若要转成下标,用 it - v.begin(),不是 std::distance(v.begin(), it)——虽然后者也对,但前者更高效且直观

自定义比较函数时 upper_bound 的写法

当容器按降序排列,或元素类型没有默认 ,就得传自定义比较函数。关键点是:比较函数语义必须和排序方式一致。

例如降序排列的 vector

std::vector v = {5, 4, 4, 3, 2, 2, 1}; // 降序 auto it = std::upper_bound(v.begin(), v.end(), 3, std::greater()); // 找第一个 < 3 的位置?不对!

注意:upper_bound 内部仍按“升序逻辑”理解比较函数。传 std::greater(),意味着它把“a > b”当作“a 在 b 前面”,所以整个逻辑翻转了。此时 upper_bound(..., 3, greater()) 实际找的是第一个 **小于等于 3** 的位置(因为“大于”在降序里对应“靠前”,而 upper_bound 要找“第一个不满足 comp(value, element)”的位置)。

更安全的做法是统一用升序 + 自定义谓词,或改用 std::lower_bound 配合反向逻辑。复杂场景建议先手写二分验证边界行为。

upper_bound 返回值为空或越界时怎么判断

upper_bound 永远不会崩溃,但可能返回 v.end()。这是合法且常见的,比如目标值比所有元素都大,或容器为空:

std::vector v; auto it = std::upper_bound(v.begin(), v.end(), 10); if (it == v.end()) {     // 没找到,v 为空或所有元素 ≤ 10 }
  • 永远不要对 v.end() 解引用(*it 会未定义行为)
  • 不要用 it == v.begin() 判断“没找到”——它可能恰好指向首元素(比如所有元素都大于目标值)
  • 若需知道是否存在大于目标值的元素,只比较 it != v.end() 即可

真正容易被忽略的是:当目标值本身不存在于序列中,upper_boundlower_bound 可能返回同一位置。这时候仅靠返回值无法区分“等于不存在”还是“大于不存在”,得结合上下文或额外检查。

text=ZqhQzanResources