std:: equal_range
|
定义于头文件
<algorithm>
|
||
| (1) | ||
|
template
<
class
ForwardIt,
class
T
>
std::
pair
<
ForwardIt, ForwardIt
>
|
(自 C++20 起为 constexpr)
(C++26 前) |
|
|
template
<
class
ForwardIt,
class
T
=
typename
std::
iterator_traits
<
ForwardIt
>
::
value_type
>
|
(自 C++26 起) | |
| (2) | ||
|
template
<
class
ForwardIt,
class
T,
class
Compare
>
std::
pair
<
ForwardIt, ForwardIt
>
|
(自 C++20 起为 constexpr)
(C++26 前) |
|
|
template
<
class
ForwardIt,
class
T
=
typename
std::
iterator_traits
<
ForwardIt
>
::
value_type
,
|
(自 C++26 起) | |
返回一个范围,包含已分区范围
[
first
,
last
)
中所有与
value
等价的元素。
|
返回 std:: lower_bound ( first, last, value ) 和 std:: upper_bound ( first, last, value ) 的结果。 若满足以下任意条件,则行为未定义:
|
(C++20 前) |
|
等价于 std :: equal_range ( first, last, value, std:: less { } ) 。 |
(C++20 起) |
-
对于范围
[first,last)中的任何元素 elem , bool ( comp ( elem, value ) ) 不能推导出 ! bool ( comp ( value, elem ) ) 。 -
范围
[first,last)中的元素 elem 未针对表达式 bool ( comp ( elem, value ) ) 和 ! bool ( comp ( value, elem ) ) 进行 分区 。
目录 |
参数
| first, last | - | 定义待检查元素分区 范围 的迭代器对 |
| value | - | 用于与元素比较的值 |
| comp | - |
二元谓词,若第一参数排序于第二参数之前则返回
true
。
谓词函数的签名应等价于如下形式: bool pred ( const Type1 & a, const Type2 & b ) ;
虽然签名不必包含
const
&
,但函数不得修改传递的对象,且必须能接受所有(可能为 const 的)
|
| 类型要求 | ||
-
ForwardIt
必须满足
LegacyForwardIterator
的要求。
|
||
-
Compare
必须满足
BinaryPredicate
的要求,但不必满足
Compare
的要求。
|
||
返回值
一个 std::pair 包含一对迭代器,其中
-
first是指向范围[first,last)中首个不小于 value 的元素的迭代器(若未找到此类元素则为 last ),且 -
second是指向范围[first,last)中首个大于 value 的元素的迭代器(若未找到此类元素则为 last )。
复杂度
给定 N 为 std:: distance ( first, last ) :
然而,若
ForwardIt
不满足
LegacyRandomAccessIterator
要求,迭代器递增次数与
N
呈线性关系。特别需要注意的是,
std::set
和
std::multiset
的迭代器不支持随机访问,因此应当优先使用其成员函数
std::set::equal_range
(相应地,对于
std::multiset::equal_range
也是如此)。
注释
尽管
std::equal_range
仅要求
[
first
,
last
)
被划分,但该算法通常用于
[
first
,
last
)
已排序的情况,这样二分搜索对任意
value
都有效。
除了满足
std::lower_bound
和
std::upper_bound
的要求外,
std::equal_range
还要求
operator
<
或
comp
具有反对称性(即
a
<
b
和
b
<
a
的结果总是相反的)。
因此,二分查找的中间结果可以被
std::lower_bound
和
std::upper_bound
共享。例如,
std::lower_bound
调用的结果可以作为
first
参数用于
std::upper_bound
调用。
| 功能测试 宏 | 值 | 标准 | 功能 |
|---|---|---|---|
__cpp_lib_algorithm_default_value_type
|
202403
|
(C++26) | 算法列表初始化 ( 1,2 ) |
可能的实现
| equal_range (1) |
|---|
template<class ForwardIt, class T = typename std::iterator_traits<ForwardIt>::value_type> constexpr std::pair<ForwardIt, ForwardIt> equal_range(ForwardIt first, ForwardIt last, const T& value) { return std::equal_range(first, last, value, std::less{}); } |
| equal_range (2) |
template<class ForwardIt, class T = typename std::iterator_traits<ForwardIt>::value_type, class Compare> constexpr std::pair<ForwardIt, ForwardIt> equal_range(ForwardIt first, ForwardIt last, const T& value, Compare comp) { return std::make_pair(std::lower_bound(first, last, value, comp), std::upper_bound(first, last, value, comp)); } |
和
标签内的C++代码
- 未翻译C++专业术语(如template、constexpr等)
- 仅翻译了表格标题中的英文文本为简体中文
示例
#include <algorithm> #include <complex> #include <iostream> #include <vector> struct S { int number; char name; // 注意:此比较运算符忽略 name 字段 bool operator<(const S& s) const { return number < s.number; } }; struct Comp { bool operator()(const S& s, int i) const { return s.number < i; } bool operator()(int i, const S& s) const { return i < s.number; } }; int main() { // 注意:未排序,仅针对下面定义的 S 进行分区 const std::vector<S> vec{{1, 'A'}, {2, 'B'}, {2, 'C'}, {2, 'D'}, {4, 'G'}, {3, 'F'}}; const S value{2, '?'}; std::cout << "使用 S::operator<() 进行比较: "; const auto p = std::equal_range(vec.begin(), vec.end(), value); for (auto it = p.first; it != p.second; ++it) std::cout << it->name << ' '; std::cout << '\n'; std::cout << "使用异构比较: "; const auto p2 = std::equal_range(vec.begin(), vec.end(), 2, Comp{}); for (auto it = p2.first; it != p2.second; ++it) std::cout << it->name << ' '; 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_type auto p3 = std::equal_range(nums.cbegin(), nums.cend(), {2, 0}, cmpz); #else auto p3 = std::equal_range(nums.cbegin(), nums.cend(), CD{2, 0}, cmpz); #endif for (auto it = p3.first; it != p3.second; ++it) std::cout << *it << ' '; std::cout << '\n'; }
输出:
使用 S::operator<() 进行比较: B C D 使用异构比较: B C D (2,2) (2, 1)
缺陷报告
下列行为变更缺陷报告被追溯应用于先前发布的C++标准。
| 缺陷报告 | 适用范围 | 发布时行为 | 正确行为 |
|---|---|---|---|
| LWG 270 | C++98 |
Compare
被要求满足
Compare
且
T
被要求
为 LessThanComparable (要求严格弱序) |
仅需满足划分要求;
允许异构比较 |
| LWG 384 | C++98 |
最多允许
2log
2
(N)+1
次比较
该要求无法实现 [1] |
修正为 2log 2 (N)+O(1) |
-
↑
对单元素范围应用
equal_range需要 2 次比较,但复杂度要求最多允许 1 次比较。
参见
|
返回指向首个
不小于
给定值的元素的迭代器
(函数模板) |
|
|
返回指向首个
大于
某值的元素的迭代器
(函数模板) |
|
|
判断元素是否存在于部分有序范围内
(函数模板) |
|
|
将元素范围划分为两组
(函数模板) |
|
|
判断两组元素是否相同
(函数模板) |
|
|
返回匹配特定键的元素范围
(
std::set<Key,Compare,Allocator>
的公开成员函数)
|
|
|
返回匹配特定键的元素范围
(
std::multiset<Key,Compare,Allocator>
的公开成员函数)
|
|
|
(C++20)
|
返回匹配特定键的元素范围
(算法函数对象) |