std::upper_bound
在标头 <algorithm> 定义 | ||
(1) | ||
template<class ForwardIt, class T > ForwardIt upper_bound( ForwardIt first, ForwardIt last, | (C++20 起为 constexpr )(C++26 前) | |
template<class ForwardIt, class T =typenamestd::iterator_traits <ForwardIt>::value_type> | (C++26 起) | |
(2) | ||
template<class ForwardIt, class T, class Compare > ForwardIt upper_bound( ForwardIt first, ForwardIt last, | (C++20 起为 constexpr )(C++26 前) | |
template<class ForwardIt, class T =typenamestd::iterator_traits <ForwardIt>::value_type, | (C++26 起) | |
在已划分的范围 [
first,
last)
中查找第一个后序于 value 的元素。
返回 如果 | (C++20 前) |
等价于 std::upper_bound(first, last, value, std::less{})。 | (C++20 起) |
[
first,
last)
中首个使得 bool(comp(value, *iter)) 是 true 的迭代器 iter,或者在不存在这种 iter 的情况下返回 last。目录 |
[编辑]参数
first, last | - | 要检验的已划分元素范围的迭代器对 |
value | - | 要与元素比较的值 |
comp | - | 如果第一个实参先序于第二个则返回 true 的二元谓词 谓词函数的签名应等价于如下: bool pred(const Type1 &a, const Type2 &b); 虽然签名不必有 const& ,函数也不能修改传递给它的对象,而且必须接受(可为 const 的)类型 |
类型要求 | ||
-ForwardIt 必须满足老式向前迭代器(LegacyForwardIterator) 。 | ||
-Compare 必须满足二元谓词(BinaryPredicate) 。不要求满足 比较(Compare) 。 |
[编辑]返回值
返回到范围 [
first,
last)
的第一个后序于 value 的元素的迭代器,或者在找不到这种元素时返回 last。
[编辑]复杂度
给定 N 为 std::distance(first, last):
然而,如果 ForwardIt
不是老式随机访问迭代器(LegacyRandomAccessIterator) ,那么迭代器自增次数与 N 成线性。要注意 std::map、std::multimap、std::set 和 std::multiset 的迭代器不是随机访问的,因此它们的 upper_bound
成员函数的表现更好。
[编辑]可能的实现
upper_bound (1) |
---|
template<class ForwardIt, class T =typenamestd::iterator_traits<ForwardIt>::value_type> ForwardIt upper_bound(ForwardIt first, ForwardIt last, const T& value){return std::upper_bound(first, last, value, std::less{});} |
upper_bound (2) |
template<class ForwardIt, class T =typenamestd::iterator_traits<ForwardIt>::value_type, class Compare> ForwardIt upper_bound(ForwardIt first, ForwardIt last, const T& value, Compare comp){ ForwardIt it;typenamestd::iterator_traits<ForwardIt>::difference_type count, step; count =std::distance(first, last); while(count >0){ it = first; step = count /2;std::advance(it, step); if(!comp(value, *it)){ first =++it; count -= step +1;}else count = step;} return first;} |
[编辑]注解
尽管 std::upper_bound
只要求 [
first,
last)
已划分,但是该算法通常会在 [
first,
last)
已排序的情况下使用,此时二分查找对于任意 value 都有效。
对于 [
first,
last)
中的任意迭代器 iter,std::upper_bound
要求 value <*iter 和 comp(value, *iter) 良构,而 std::lower_bound 要求 *iter < value 和 comp(*iter, value) 良构。
功能特性测试宏 | 值 | 标准 | 功能特性 |
---|---|---|---|
__cpp_lib_algorithm_default_value_type | 202403 | (C++26) | 算法中的列表初始化(1,2) |
[编辑]示例
#include <algorithm>#include <cassert>#include <complex>#include <iostream>#include <vector> struct PriceInfo {double price;}; int main(){conststd::vector<int> data{1, 2, 4, 5, 5, 6}; for(int i =0; i <7;++i){// 搜索首个大于 i 的元素auto upper = std::upper_bound(data.begin(), data.end(), i); std::cout<< i <<" < "; upper != data.end()?std::cout<<*upper <<" 位于索引 "<<std::distance(data.begin(), upper):std::cout<<"没有找到";std::cout<<'\n';} std::vector<PriceInfo> prices ={{100.0}, {101.5}, {102.5}, {102.5}, {107.3}}; for(double to_find :{102.5, 110.2}){auto prc_info = std::upper_bound(prices.begin(), prices.end(), to_find, [](double value, const PriceInfo& info){return value < info.price;}); prc_info != prices.end()?std::cout<< prc_info->price <<" 位于索引 "<< prc_info - prices.begin():std::cout<< to_find <<" 没有找到";std::cout<<'\n';} using CD =std::complex<double>;std::vector<CD> nums{{1, 0}, {2, 2}, {2, 1}, {3, 0}, {3, 1}};auto cmpz =[](CD x, CD y){return x.real()< y.real();};#ifdef __cpp_lib_algorithm_default_value_typeauto it = std::upper_bound(nums.cbegin(), nums.cend(), {2, 0}, cmpz);#elseauto it = std::upper_bound(nums.cbegin(), nums.cend(), CD{2, 0}, cmpz);#endifassert((*it == CD{3, 0}));}
输出:
0 < 1 位于索引 0 1 < 2 位于索引 1 2 < 4 位于索引 2 3 < 4 位于索引 2 4 < 5 位于索引 3 5 < 6 位于索引 5 6 < 没有找到 107.3 位于索引 4 110.2 没有找到
[编辑]缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
缺陷报告 | 应用于 | 出版时的行为 | 正确行为 |
---|---|---|---|
LWG 270 | C++98 | Compare 需要满足比较(Compare) ,并且 T 需要是可小于比较(LessThanComparable) 的(要求严格弱序) | 只需要划分; 容许异相比较 |
LWG 384 | C++98 | 最多允许 log2(N)+1 次比较 | 改成 log2(N)+O(1) 次 |
LWG 577 | C++98 | 不能返回 last | 可以返回 |
LWG 2150 | C++98 | 如果 [ first, last) 中存在任何迭代器 iter 使得bool(comp(value, *iter)) 是 true,那么 std::upper_bound 可以返回 [ iter, last) 中的任意迭代器 | 不能返回 iter 后的迭代器 |
[编辑]参阅
返回匹配特定键值的元素范围 (函数模板) | |
返回首个不小于 给定值的元素的迭代器 (函数模板) | |
将范围中元素分为两组 (函数模板) | |
(C++11) | 定位已划分范围的划分点 (函数模板) |
(C++20) | 返回首个大于 给定值的元素的迭代器 (算法函数对象) |
返回指向首个大于 给定键的元素的迭代器 ( std::set<Key,Compare,Allocator> 的公开成员函数) | |
返回指向首个大于 给定键的元素的迭代器 ( std::multiset<Key,Compare,Allocator> 的公开成员函数) |