C++中std::map容器中元素删除方法汇总 - 详解

news/2025/9/22 22:34:50/文章来源:https://www.cnblogs.com/ljbguanli/p/19106254

C++中std::map容器中元素删除方法汇总 - 详解

1. std::map 的基本特点

  • 有序关联容器,按 key 排序存储。
  • 内部通常为 红黑树(平衡二叉搜索树)。
  • key 唯一,value 可修改。
  • 查找、插入、删除复杂度均为 O(log n)

2. 删除元素的基本方法

2.1 使用 key 删除

std::map<
int, std::string> m = {
{
1,"a"
}, {
2,"b"
}, {
3,"c"
}
};
// 删除 key=2 的元素
size_t removed = m.erase(2);
// 返回删除元素数量(0 或 1)
  • 复杂度:O(log n)
  • 注意:如果 key 不存在,返回 0。
  • 适用场景:知道要删除的元素 key。

2.2 使用迭代器删除单个元素

auto it = m.find(3);
if(it != m.end()) {
m.erase(it);
}
  • 复杂度:O(log n)(查找)+ O(1)(删除节点)
  • 优点:可以在迭代过程中安全删除元素(需注意 ++it 避免失效)
  • 注意erase(it) 会使该迭代器失效,但其他迭代器不受影响。

2.3 使用迭代器范围删除

// 删除 key 从 1 到 2(不包含 2)
m.erase(m.begin(), m.find(2));
  • 复杂度:O(log n + k),k 为删除元素个数

  • 注意

    • 左闭右开区间 [first, last)
    • 删除范围过大时,仍是高效操作,因为底层红黑树会做局部重平衡。

2.4 清空整个 map

m.clear();
// 删除所有元素
  • 复杂度:O(n)
  • 效果:调用每个元素的析构函数,释放内存。

3. 删除元素的迭代安全写法

在遍历 map 时删除元素,需要小心迭代器失效问题:

3.1 正确写法

for(auto it = m.begin(); it != m.end();
) {
if(it->second == "b") {
it = m.erase(it);
// erase 返回下一个有效迭代器
} else {
++it;
}
}
  • 核心erase 返回指向下一个元素的迭代器,避免使用已失效的迭代器。
  • 错误示例
for(auto it = m.begin(); it != m.end();
++it) {
if(it->second == "b") {
m.erase(it);
// 错误!it 失效,下一步 ++it 未定义行为
}
}

4. 删除元素时的复杂度分析

方法时间复杂度备注
erase(key)O(log n)单元素删除
erase(iterator)O(1) 删除节点 + O(log n) 重平衡已知迭代器,删除效率高
erase(iterator_first, iterator_last)O(k + log n)k 为删除元素个数
clear()O(n)遍历析构每个元素

小结:若要删除大量元素,使用范围删除比单个 key 删除更高效。


5. 高级技巧

5.1 条件删除(lambda + erase_if)

C++20 提供 std::erase_if

#include <map>#include <algorithm>std::map<int,std::string> m = {{1,"a"}, {2,"b"}, {3,"c"}};// 删除 value == "b" 的元素std::erase_if(m, [](auto &pair){return pair.second == "b";});
  • 简化遍历删除操作
  • 底层安全迭代器处理
  • 兼容 STL 容器,包含 vector/map/set

5.2 使用 find + 条件删除

auto it = m.find(2);
if(it != m.end() && it->second == "b") {
m.erase(it);
}
  • 适用于复杂条件判断

6. 内存与性能注意点

  1. erase 会调用元素的析构函数,复杂对象可能开销大。

  2. 如果大量删除后还要插入新元素,map 内部可能会频繁重平衡,考虑:

    • 使用 unordered_map(哈希表)删除复杂度均摊 O(1)
    • 批量删除而不是循环单个删除
  3. 对于大数据 SLAM 系统,频繁删除 map 中点云或特征索引时,可以:

    • 使用 内存池 存储 value,避免频繁分配/释放
    • 或使用 std::vector + 索引表 做批量逻辑删除,提高缓存局部性

7. std::map 的各种删除元素综合示例

示例1
下面展示 std::map 的各种删除元素方法,包括:按 key 删除、按 iterator 删除、按条件删除(比如满足某个条件的元素),并配合一些遍历操作来看效果。

#include <iostream>#include <map>#include <string>int main() {// 创建一个 std::mapstd::map<int, std::string> myMap = {{1, "apple"},{2, "banana"},{3, "cherry"},{4, "date"},{5, "elderberry"}};std::cout <<"初始 map:" << std::endl;for (const auto&[key, value] : myMap) {std::cout << key <<" -> " << value << std::endl;}// 方法1:按 key 删除std::cout <<"\n删除 key=2 的元素" << std::endl;myMap.erase(2);// 返回值是删除的元素数量for (const auto&[key, value] : myMap) {std::cout << key <<" -> " << value << std::endl;}// 方法2:按 iterator 删除std::cout <<"\n删除第一个元素" << std::endl;auto it = myMap.begin();myMap.erase(it);for (const auto&[key, value] : myMap) {std::cout << key <<" -> " << value << std::endl;}// 方法3:按条件删除(删除 key > 3 的元素)std::cout <<"\n删除 key > 3 的元素" << std::endl;for (auto iter = myMap.begin(); iter != myMap.end();) {if (iter->first >3) {iter = myMap.erase(iter);// erase 返回下一个有效 iterator} else {++iter;}}for (const auto&[key, value] : myMap) {std::cout << key <<" -> " << value << std::endl;}// 方法4:清空整个 mapstd::cout <<"\n清空整个 map" << std::endl;myMap.clear();std::cout <<"map 大小: " << myMap.size() << std::endl;return 0;}

输出示例:

初始 map:
1 -> apple
2 -> banana
3 -> cherry
4 -> date
5 -> elderberry
删除 key=2 的元素
1 -> apple
3 -> cherry
4 -> date
5 -> elderberry
删除第一个元素
3 -> cherry
4 -> date
5 -> elderberry
删除 key > 3 的元素
3 -> cherry
4 -> date
清空整个 map
map 大小: 0

示例2
下面一个更高级的示例,演示如何在循环中 安全删除满足复杂条件的多个元素,同时避免 iterator 失效问题。这里用 std::map::erase 返回的新 iterator 来保证安全。

#include <iostream>#include <map>#include <string>int main() {std::map<int, std::string> myMap = {{1, "apple"},{2, "banana"},{3, "cherry"},{4, "date"},{5, "elderberry"},{6, "fig"},{7, "grape"}};std::cout <<"初始 map:" << std::endl;for (const auto&[key, value] : myMap) {std::cout << key <<" -> " << value << std::endl;}// 高级删除:删除所有 key 为奇数或者 value 长度 > 5 的元素for (auto it = myMap.begin(); it != myMap.end();) {if (it->first % 2 != 0 || it->second.length() >5) {// erase 返回删除元素后的下一个有效 iteratorit = myMap.erase(it);} else {++it;}}std::cout <<"\n删除奇数 key 或 value 长度 > 5 的元素后:" << std::endl;for (const auto&[key, value] : myMap) {std::cout << key <<" -> " << value << std::endl;}return 0;}

输出示例:

初始 map:
1 -> apple
2 -> banana
3 -> cherry
4 -> date
5 -> elderberry
6 -> fig
7 -> grape
删除奇数 key 或 value 长度 > 5 的元素后:
4 -> date
6 -> fig

重点说明:

  1. 不要在循环中直接用 ++iterase(it) 分开,因为 erase(it) 会使当前 iterator 失效。
  2. 正确方式:用 it = myMap.erase(it)erase 会返回下一个有效 iterator。
  3. 这种方法适用于复杂条件删除,非常安全。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/910603.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

物理半程与半时问题

本文旨在深入解析匀变速直线运动中常见的“半程问题”和“半时问题”,通过公式推导、多种方法比较以及物理意义的阐释,帮助你理解两者在平均速度上的差异及其内在原因。物理半程与半时问题 本文旨在深入解析匀变速直…

网站展现形式网站seo优化课程

一.简单实例&#xff1a; 1.实例要求 点击按钮&#xff0c;实现 >o<与#-#的转换。 2.步骤 补充&#xff1a;​​​​​​​ 1.如果我想在lambda中修改数据&#xff0c;怎么办&#xff1f; 写上mutable就行。

加盟网站做推广怎么收费营销型网站建设制作推广

文章目录 1. 前言2. 错误情况3. 解决办法3.1 获取gradle下载地址3.2 获取gradle存放目录3.3 替换并删除临时文件3.4 触发Try Again 4. 执行成功 1. 前言 今天调试项目&#xff0c;发现新装的AS&#xff0c;在下载gradle的过程中&#xff0c;一直显示连接失败&#xff0c;Gradl…

成都网站建设设计公司上海网站建设 劲晟

Innodb引擎Innodb引擎提供了对数据库ACID事务的支持&#xff0c;并且实现了SQL标准的四种隔离级别。该引擎还提供了行级锁和外键约束&#xff0c;它的设计目标是处理大容量数据库系统&#xff0c;它本身其实就是基于MySQL后台的完整数据库系统&#xff0c;MySQL运行时Innodb会在…

信息门户网站制作费用辽宁省建设厅网站升级

戳蓝字“CSDN云计算”关注我们哦&#xff01;技术头条&#xff1a;干货、简洁、多维全面。更多云计算精华知识尽在眼前&#xff0c;get要点、solve难题&#xff0c;统统不在话下&#xff01;Gartner公司已列出了2019年及以后影响平台即服务&#xff08;PaaS&#xff09;技术和平…

南京网站优化建站二级域名发放免费

一,安装JBOSS&#xff1a;安装JBOSS很简单。将jboss-4.0.4.GA.zip解压到一个目录(比如d:\ jboss-4.0.4.GA)下即可。提示&#xff1a;保留原来的zip文件&#xff0c;以免在使用过程中出错&#xff0c;还可以恢复到正常状态。二&#xff0c;运行JBOSS:在JBOSS的home目录(即$JBOSS…

9.22 科研小结:不要总是预设成功,失败才是常态

今天早上首先把main和augment的训练测试代码补全,还是不太能独立开发代码,基本功需要多夯实,尤其是一些基本库基本函数的使用,什么时候用axis什么时候用dim,还有就是代码结构思维,在写一个类的时候首先思考它的作…

STM32光强传感器实验详解 - 实践

STM32光强传感器实验详解 - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco&qu…

在CodeBolcks下wxSmith的C++编程教程——从Hello world开始讲述wxSmith使用基础

0.前言 欢迎来到 wxSmith 教程页面!wxSmith 与 Code::Blocks、wxWidgets 和 C++ 编译器相结合,为您提供一种所见即所得的方式来创建具有图形用户界面 (GUI) 的应用程序。该组合形成了一个用于快速应用程序开发 (…

详细介绍:C 语言内存操作函数:memcpy、memmove、memset、memcmp 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

网站做优化的必要性wordpress用户角色管理

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 因为做牛客的题目…

小学校园门户网站建设做情网站

Scrapy核心组件与运行机制 引言 这一章开始讲解Scrapy核心组件的功能与作用&#xff0c;通过流程图了解整体的运行机制&#xff0c;然后了解它的安装与项目创建&#xff0c;为后续实战做好准备。 Scrapy定义 Scrapy是一个为了爬取网站数据、提取结构性数据而编写的应用框架…

安徽元鼎建设工程网站自助建站系统官方版

什么是Elastic AMPElastic APM 是一个应用程序性能监控系统。它可以请求的响应时间、数据库查询、对缓存的调用、外部 HTTP 请求等的详细性能信息&#xff0c;可以实时监控软件服务和应用程序。这可以帮助我们快速查明和修复性能问题。Elastic APM 还会自动收集未处理的错误和异…

汉川做网站网站策划搭建方案

问题描述&#xff1a; 今天在写csdn动态的时候&#xff0c;发了五个动态&#xff0c;但是主页面的“最近”看不到我发的动态&#xff0c;我还以为是csdn动态每天的发送量有数量限制。去这个地方点我的发现 右上角全是“审核中”的字样 按理说是不可能审核这么久的&#xff08…

如何制作自己的网站 可放广告西安seo关键词排名优化

一&#xff1a;背景 1. 讲故事这个月初&#xff0c;星球里的一位朋友找到我&#xff0c;说他的程序出现了死锁&#xff0c;怀疑是自己的某些写法导致mongodb出现了如此尴尬的情况&#xff0c;截图如下&#xff1a;说实话&#xff0c;看过这么多dump&#xff0c;还是第一次遇到真…

怎么直接用代码做网站手机 pc网站模板

左右指针 前言一、双指针算法二、左右指针1.用于在已排序数组中找到两个数使其和为特定值2.在字符串中判断是否为回文 总结 前言 今天在刷Leetcode的时候觉得自己双指针掌握的还是不错的记录一下,写个学习笔记,也方便以后翻阅,如果也帮助到你了,那真是太好啦! 本篇介绍的是左右…

滁州网站建设czesou网站群建设情况

一、什么是Redis Redis是一种基于内存的数据库&#xff0c;对数据的读写操作都是在内存中完成&#xff0c;因此读写速度非常快&#xff0c;用于存储键值对、缓存、消息队列、分布式锁等。 二、Redis和mencached的区别 相同&#xff1a;都是基于内存的数据库&#xff0c;读写都…

网站建设有关的软件重庆微信网站制作价格

目录 gdb工具的使用 代码调试相关指令 运行程序指令 r 显示代码的指令 l 给代码打断点 b 查看断点位置 info b 执行代码到断点处停止 关闭断点 d断点编号 关闭某个断点&#xff0c;但不删除 disable编号 打开某个断点 enable断点编号 逐过程调试代码 n 逐语句调试代码 s 查看…

湖南网站营销推广设计滨州做网站优化

1 python新式类变化统一类和类型 python新式类从2.2版本引入。 &#xff08;1&#xff09;新式类继承内置类型 (比如object&#xff0c;list&#xff0c;dict等)&#xff0c;经典类不继承任何类。 &#xff08;2&#xff09;python2&#xff0c;定义类时&#xff0c;显式继承…

今天做什么

练习java的项目分解