std::equal_range在有序序列中查找目标值的左闭右开相等区间,返回first(首个≥目标)和second(首个>目标)迭代器;需确保容器已排序且比较器满足严格弱序,否则行为未定义。

std::equal_range 查的是“等于某值”的左闭右开区间
它返回一个 std::pair,其中 first 指向第一个不小于目标值的元素,second 指向第一个大于目标值的元素。当容器有序且含重复项时,这两者正好框住所有等于目标的元素——也就是你要的“重复元素范围”。
关键前提:必须用在已排序的序列上(比如 std::vector 调过 std::sort,或 std::set),否则行为未定义。
常见错误现象:std::equal_range 返回空范围(it == end),但你以为数据丢了——其实是容器没排好序,或者你传了错误的比较器。
- 使用场景:查
std::vector里所有5的位置;在日志时间戳数组中批量提取某秒内的全部记录 - 参数差异:第三个参数可传自定义比较函数,比如
std::equal_range(v.begin(), v.end(), key, [](int a, int b) { return a ;若省略,则默认用 - 性能影响:二分查找,
O(log n);比遍历快得多,但要求随机访问迭代器(std::list不支持)
怎么拿到重复元素的起始和结束迭代器
调用后直接解包 first 和 second 即可,别手抖写成 second - 1 去取最后一个——它本来就是右开区间,[first, second) 已经是完整范围。
立即学习“C++免费学习笔记(深入)”;
示例:
std::vectorv = {1, 2, 2, 2, 3, 4, 4};
auto range = std::equal_range(v.begin(), v.end(), 2);
// range.first → 指向索引 1 的 2
// range.second → 指向索引 4 的 3(不是最后一个 2!)
// 所以 [range.first, range.second) 包含索引 1、2、3 三个 2
- 容易踩的坑:对
std::vector用std::equal_range后,误用std::distance(range.first, range.second)计数前没确认容器是否真的有序 - 兼容性注意:C++11 起支持;若用
std::array或原生数组,记得传对begin/end迭代器,别传指针偏移出界
和 lower_bound / upper_bound 的关系别搞混
std::equal_range 等价于同时调用 std::lower_bound 和 std::upper_bound,但只做一次二分——效率更高,也更安全(避免两次调用间容器被意外修改)。
所以别这么写:
auto low = std::lower_bound(v.begin(), v.end(), x);
auto up = std::upper_bound(v.begin(), v.end(), x); // 多一次二分,且可能不一致
应该直接用:
auto range = std::equal_range(v.begin(), v.end(), x); // 一次二分,结果严格配对
- 为什么这样做:两个单独调用可能因容器变动或浮点比较误差导致
low > up,而equal_range内部保证first ≤ second - 性能影响:省掉一次
O(log n)开销;在 tight loop 或高频查询中差异明显
在 map/set 里怎么用
std::map 和 std::set 本身有序,但它们的 equal_range 成员函数(非算法版)更合适——它返回的是容器自己的迭代器类型,且针对红黑树做了优化。
别这样:
std::mapm = {{1,"a"},{2,"b"},{2,"c"}};
// 错!算法版不能直接用于 map 的 value_type
auto r = std::equal_range(m.begin(), m.end(), 2, /* ... */); // 编译失败
要这样:
auto r = m.equal_range(2); // 正确:调用 map::equal_range(key),返回 pair
- 使用场景:查
std::multimap中所有键为"user_id"的条目;std::multiset中统计某值出现次数(std::distance(r.first, r.second)) - 容易踩的坑:对
std::map(非 multimap)调equal_range总是返回最多一个元素的范围;想存重复键,必须用std::multimap
最常被忽略的一点:std::equal_range 对浮点数或自定义类型做比较时,若比较逻辑不满足严格弱序(比如用了 ),结果不可靠——排序和查找必须用同一套规则,否则连“有序”这个前提都崩了。










