c++如何使用std::multimap处理重复键_c++ 关联容器插入与区间查询【方法】

12次阅读

std::multimap适合存重复键因其底层红黑树支持键重复、自动排序且同键元素保持插入顺序;equal_range高效获取所有匹配键的区间,erase(key)可批量删除,自定义键需确保operator

c++如何使用std::multimap处理重复键_c++ 关联容器插入与区间查询【方法】

std::multimap 为什么适合存重复键

因为 std::multimap 明确允许键重复,底层是红黑树实现,自动按 key 排序,且相同 key 的元素按插入顺序(稳定)排列。这和 std::map(拒绝重复键)、std::unordered_multimap(无序、哈希)有本质区别——如果你需要「按 key 范围查 + 允许多值」,std::multimap 是最直接的选择。

插入重复键时要注意的三个细节

插入本身很简单,但容易忽略行为边界:

  • insert() 总是成功,返回 std::pair 中的 bool 恒为 true(因为允许多值),不能靠它判断“是否新增了新键”
  • emplace() 更高效,避免临时对象构造,例如:mm.emplace(42, "hello")
  • 若批量插入相同 key 的多个值,它们在迭代器遍历时**保持插入顺序**(c++11 起保证),但整个容器仍按 key 排序——也就是说,所有 key=42 的节点会连续出现,且内部有序

用 equal_range 高效查区间内所有重复键

这是处理重复键的核心操作。相比 find()(只返回一个迭代器),equal_range(key) 返回一对迭代器:std::pair,分别指向第一个等于 key 和第一个大于 key 的位置——也就是所有 key 对应值的闭左开右区间。

std::multimap mm; mm.insert({3, "a"}); mm.insert({3, "b"}); mm.insert({5, "c"});  auto range = mm.equal_range(3); for (auto it = range.first; it != range.second; ++it) {     std::cout << it->second << "n"; // 输出 "a", "b" }

注意:lower_bound(key)upper_bound(key) 单独调用也能实现同样效果,但 equal_range 通常一次二分完成,性能更稳。

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

删除指定 key 的所有值或仅删一个

删除逻辑和查询对称:

  • mm.erase(key) —— 删除所有 key 相等的元素,返回被删数量(size_t
  • mm.erase(it) —— 删除单个迭代器指向的元素(it 必须合法且未失效)
  • 想删某 key 的前 N 个?得手动遍历:auto r = mm.equal_range(key); 然后用 std::next(r.first, N) 截断并 erase 区间

别用 find() 后直接 erase(it) 来删重复键——它只删第一个匹配项,容易误判“删完了”。

真正麻烦的是:当 key 类型是自定义类时,operator 必须严格符合全序,且 equal_range 依赖它;如果比较逻辑写错,区间可能为空或越界,调试时很难一眼发现。

text=ZqhQzanResources