【C++】 详解 lower_bound 和 upper_bound 函数(绝对正确,大道至简)

网上看了一篇高评论的文章,动手操作下来发现完全错的,感觉还是好多人看各种资料看的迷糊

这篇文章就大道至简,总结用法,不纠结实现代码。

看这几条,很容易掌握规律???

        lower_bound(iter 1,iter 2,val)寻找第一个大于等于val的迭代器

        upper_bound(iter 1,iter 2,val)寻找第一个大于val的迭代器

原函数模型都是寻找大于,区别在于是否有等于号,lower大于等于,upper只大于,所以只能用于从小到大的排序

        bool cmp ( const int &val , const int &e       类型是迭代器指向 和 val(两者应一致,val和e位置不可替换,val是比较值,e是迭代器指向值)

        lower_bound(iter 1,iter 2,val,cmp寻找第一个不满足cmp的迭代器,只适用前面都满足cmp的排序,错误的例子:【1,2,3,4,5】, cmp偶数为true,最后返回3,而不是1

        upper_bound(iter 1,iter 2,val,cmp寻找第一个满足cmp的迭代器,只适用前面都不满足cmp的排序,正确的例子:【1,3,4】,cmp偶数为true,最后返回4

加入自定义cmp,lower找“第一个”不满足cmp的数,upper找“第一个”满足cmp的数。“第一个”指只适用前面都与目标数cmp条件互斥(而不是找位置上的第一个)

        lower_bound(iter 1,iter 2,val,greater<T>() 寻找第一个小于等于val的迭代器

        lower_bound(iter 1,iter 2,val,less<T>()寻找第一个大于等于val的迭代器。

lower改成upper只是少了等于的条件,其它一样。可以看出,greater只适用降序,less只适用升序。不然只会返回第一个值。

总结:

首先,两个函数必须要求已排序的内容,因为里面是二分搜索。

其次,所有查不到都返回end()。

最后,不要背,不要记,不要想——>没有规律。用的时候现查!

### STL 容器 `map` 中 `lower_bound` `upper_bound` 函数详解及二分查找原理 #### 什么是 `lower_bound` `upper_bound` 在 C++ 的 STL 中,`std::map` 是一种有序关联容器,其内部实现了红黑树结构。为了快速定位键值对中的某些特定位置,提供了两个重要的成员函数:`lower_bound` `upper_bound`[^1]。 - **`lower_bound(key)`**: 返回一个迭代器,指向第一个不小于给定键值的元素。如果没有这样的元素,则返回 `end()`。 - **`upper_bound(key)`**: 返回一个迭代器,指向第一个大于给定键值的元素。如果没有这样的元素,则返回 `end()`。 这两个函数的时间复杂度均为 \(O(\log n)\),因为它们基于二分查找算法工作[^2]。 --- #### 示例代码展示 下面是一段完整的代码示例,演示了如何使用 `lower_bound` `upper_bound`: ```cpp #include <iostream> #include <map> int main() { std::map<int, char> myMap = {{1, 'a'}, {3, 'b'}, {5, 'c'}, {7, 'd'}, {9, 'e'}}; // 使用 lower_bound 找到第一个 >= 4 的键 auto lbIt = myMap.lower_bound(4); if (lbIt != myMap.end()) { std::cout << "Lower bound of 4: (" << lbIt->first << ", " << lbIt->second << ")\n"; } else { std::cout << "No key found greater than or equal to 4.\n"; } // 使用 upper_bound 找到第一个 > 6 的键 auto ubIt = myMap.upper_bound(6); if (ubIt != myMap.end()) { std::cout << "Upper bound of 6: (" << ubIt->first << ", " << ubIt->second << ")\n"; } else { std::cout << "No key found greater than 6.\n"; } return 0; } ``` 运行结果如下: ``` Lower bound of 4: (5, c) Upper bound of 6: (7, d) ``` --- #### 二分查找的工作原理 `lower_bound` `upper_bound` 都采用了二分查找的思想来加速搜索过程。以下是其实现的核心逻辑: 1. 初始时设定左指针 `left` 指向起始位置,右指针 `right` 指向结束位置前一位。 2. 计算中间索引 `mid = left + (right - left) / 2`,避免溢出。 3. 将目标值与当前中间位置的关键字进行比较: - 若关键字小于目标值,则更新 `left = mid + 1`; - 否则,更新 `right = mid`。 4. 循环直到 `left == right`,此时得到的结果即为目标位置。 由于 `std::map` 内部已经按照键值排序,因此可以直接应用上述二分查找策略[^4]。 --- #### 自定义比较准则的应用 当需要处理复杂的键值类型或自定义排序规则时,可以通过传递额外的比较函数实现定制化的行为。例如: ```cpp #include <iostream> #include <vector> #include <algorithm> struct CustomComparator { bool operator()(const int& lhs, const int& rhs) const { return lhs > rhs; // 降序排列 } }; int main() { std::vector<int> vec = {5, 3, 8, 1, 4}; std::sort(vec.begin(), vec.end(), CustomComparator()); auto it = std::lower_bound(vec.begin(), vec.end(), 4, CustomComparator()); if (it != vec.end()) { std::cout << "Custom Lower Bound: " << *it << "\n"; // 输出 4 } return 0; } ``` 在此例子中,我们通过重载运算符的方式创建了一个降序比较器,并将其应用于 `lower_bound` 函数中[^5]。 --- #### 插入新元素的影响 值得注意的是,每当有新的键值被插入到 `std::map` 中时,原有的顺序会被自动维护,不会破坏后续调用 `lower_bound` 或 `upper_bound` 的正确性[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值