【深入C++】map和set的使用
文章目录
- C++ 中的容器分类
- 1. 顺序容器
- 2. 关联容器
- 3. 无序容器
- 4. 容器适配器
- 5. 字符串容器
- 6. 特殊容器
- set
- 1.构造函数
- 2.迭代器
- 3.容量相关的成员函数
- 4.修改器类的成员函数
- 5.容器相关操作的成员函数
- multiset
- 1.equal_range
- map
- 1.初始化相关的函数
- 2.迭代器
- 3.容量相关的成员函数
- 4.访问相关的成员函数
- 5.修改器类的成员函数
- 6.容器相关操作的成员函数
- 总结


C++ 中的容器分类
在C++中,标准库提供了多种容器,这些容器可以根据其数据存储方式和功能进行分类。以下是C++中常见容器的分类:
1. 顺序容器
这些容器按顺序存储元素,适用于需要保持元素顺序的场景。
- vector: 动态数组,支持快速随机访问和在末尾高效插入和删除操作。
- deque: 双端队列,支持快速随机访问和在两端高效插入和删除操作。
- list: 双向链表,支持在任何位置高效插入和删除操作,但随机访问较慢。
- forward_list: 单向链表,只支持在头部高效插入和删除操作。
- array: 固定大小的数组,大小在编译时确定。
2. 关联容器
这些容器根据键值对存储元素,并自动按键排序,适用于需要快速查找的场景。
- set: 集合,存储唯一的元素,元素自动按键排序。
- multiset: 允许重复元素的集合,元素自动按键排序。
- map: 键值对存储的映射,键唯一且自动排序。
- multimap: 允许重复键的映射,键自动排序。
3. 无序容器
这些容器使用哈希表存储元素,适用于需要快速查找和插入的场景,但不保证元素顺序。
- unordered_set: 无序集合,存储唯一的元素。
- unordered_multiset: 无序多重集合,允许重复元素。
- unordered_map: 无序映射,键唯一。
- unordered_multimap: 无序多重映射,允许重复键。
4. 容器适配器
这些不是独立的容器,而是对现有容器的包装,提供特定用途的接口。
- stack: 栈,后进先出(LIFO)结构,通常使用deque或vector实现。
- queue: 队列,先进先出(FIFO)结构,通常使用deque或list实现。
- priority_queue: 优先队列,元素按优先级排序,通常使用vector和heap算法实现。
5. 字符串容器
- string: 用于存储和操作字符序列,类似于动态数组,但专门针对字符。
6. 特殊容器
- bitset: 固定大小的二进制数组,提供按位操作。
这些容器各有优缺点和适用场景,选择合适的容器可以显著提高程序的性能和可维护性。
这篇文章讲的两个容器都是关联式容器
set

在C++标准库中,set容器的底层实现通常是基于红黑树这种自平衡二叉搜索树。红黑树是一种能够在插入、删除和查找操作中保持对数时间复杂度的树结构。
1.构造函数

构造函数主要分为三个:无参构造,迭代器区间构造,拷贝构造
无参构造:
set<int> s;
迭代器区间构造:
vector<int> v{ 1,2,3,4,5,6,7 };
set<int> s(v.begin(), v.end());
拷贝构造:
set<int> s1{ 1,2,3,4 };
set<int> s2(s1);
赋值拷贝
set<int> s1{ 1,2,3,4 };
set<int> s2;
s2 = s1;
2.迭代器

迭代器遍历:
auto it = s1.begin();
while (it != s1.end())
{cout << *it << ' ';it++;
}
范围for:
for (auto e : s1)
{cout << e << ' ';
}
3.容量相关的成员函数

int main()
{set<int> s1{ 1,2,3,4 };cout << s1.size() << endl;//4cout << s1.empty() << endl;//0return 0;
}
4.修改器类的成员函数

insert:
有三个重载函数

支持迭代器区间插入。
int main()
{set<int> s1;s1.insert(2);s1.insert(3);s1.insert(6);s1.insert(1);s1.insert(5);s1.insert(7);for (auto e : s1){cout << e << ' ';}return 0;
}
erase:

第二个重载函数:
int num = s1.erase(3);
cout << endl << num << endl;
删除成功返回1,删除失败返回0。
5.容器相关操作的成员函数

find:
int main()
{set<int> s1;s1.insert(2);s1.insert(3);s1.insert(6);s1.insert(1);s1.insert(5);s1.insert(7);auto it = s1.find(2);if (it != s1.end()) cout << *it << endl;else cout << "does not exist" << endl;return 0;
}
如果找到了返回找到的迭代器,如果没有找到则返回的是end()。
count:
count返回的是对应元素的个数:在set中存在就返回1,不存在就返回0。

lower_bound:
lower_bound返回的是大于等于某个数的。
int main()
{set<int> s1;s1.insert(2);s1.insert(3);s1.insert(6);s1.insert(1);s1.insert(5);s1.insert(7);auto lower = s1.lower_bound(4);cout << *lower << endl;return 0;
}
这里输出的是大于等于4的数,所以这里输出的是5。
upper_bound:
auto upper = s1.upper_bound(6);
cout << *upper << endl;
这里输出的是大于6的数,所以输出的是7。
set有一个致命的缺陷,在插入重复数据时,是插入不进去的,所以这里我们需要了解multiset。
multiset

multiset和set唯一不同的区别是一个支持插入重复数据,一个不支持。
int main()
{set<int> s1;s1.insert(1);s1.insert(1);s1.insert(1);s1.insert(1);for (auto e : s1) cout << e << ' ';multiset<int> s2;s2.insert(1);s2.insert(1);s2.insert(1);s2.insert(1);cout << endl;for (auto e : s2)cout << e << ' ';return 0;
}
可以set不支持插入重复数据,multiset支持插入重复数据。

在查找数据的时候multiset查找的是第一个数据。
删除数据:multiset删除数据,删除的是所有重复的数据,而不是删除第一个数据。
1.equal_range
int main()
{multiset<int> s{ 1,1,4,4,4,3,3,3,3,3,5,5,5, 6 };auto [a, b] = s.equal_range(3);s.erase(a, b);for (auto e : s){cout << e << ' ';}
}
equal_range可以求出指定值的范围区域,两个迭代器。
一个首一个尾。
map

map属于KV模型,用一个k值索引v值。
在C++标准库中,map 容器的底层实现通常是基于红黑树(Red-Black Tree)这种自平衡二叉搜索树(Self-balancing Binary Search Tree)。红黑树是一种能够在插入、删除和查找操作中保持对数时间复杂度的树结构。
1.初始化相关的函数

构造函数:

map和set的构造方式是一样的,也是三种构造函数。
2.迭代器

map的迭代器和set的迭代器稍有区别,但不多。
返回for:
int main()
{map<int, char> m{ { 1,'a' } ,{ 2,'b' },{ 3,'c' },{ 4,'d' },{ 5,'e' } };for (auto e : m)cout << e.first << ':' << e.second << endl;
}
迭代器区间遍历:
int main()
{map<int, char> m{ { 1,'a' } ,{ 2,'b' },{ 3,'c' },{ 4,'d' },{ 5,'e' } };auto it = m.begin();while (it != m.end()){cout << it->first << ':' << it->second << endl;it++;}
}
结构化绑定:
int main()
{map<int, char> m{ { 1,'a' } ,{ 2,'b' },{ 3,'c' },{ 4,'d' },{ 5,'e' } };for (auto [a, b] : m)cout << a << ':' << b << endl;
}
3.容量相关的成员函数

和set的用法大差不差。
4.访问相关的成员函数

operator[]:
int main()
{map<int, char> m{ { 1,'a' } ,{ 2,'b' },{ 3,'c' },{ 4,'d' },{ 5,'e' } };cout << m[1] << endl;cout << m[2] << endl;cout << m[3] << endl;
}
map可以通过一个成员的第一个键值来索引当前成员的第二个键值,就是用key索引value。
at:
int main()
{map<int, char> m{ { 1,'a' } ,{ 2,'b' },{ 3,'c' },{ 4,'d' },{ 5,'e' } };cout << m.at(1) << endl;
}
用at进行索引value。

可以看见如果容器当中没有当前值的索引,则会抛出异常。
5.修改器类的成员函数

这里修改器类的成员函数和set相同,但是insert,需要插入一个键值对:
m.insert({ 6,'f' });
m.insert(pair<int, char>(6, 'f'));
m.insert(make_pair(6, 'f'));
6.容器相关操作的成员函数

这些和set都是一样的。
总结
在本篇博客中,我们深入探讨了C++标准库中的map和set容器。通过详细的示例和解释,我们了解了它们的基本用法、常用操作以及在不同场景下的应用。map和set不仅为我们提供了高效的键值对存储和有序集合管理功能,还在复杂数据结构和算法设计中扮演了重要角色。
掌握map和set的使用,不仅能够提升我们的编程效率,还能帮助我们编写出更为高效和可靠的代码。在实际开发中,合理地选择和使用这些容器,可以显著优化程序的性能和可维护性。
希望通过这篇博客,大家能够对map和set有更深入的理解,并在以后的编程实践中灵活运用它们。如果你有任何疑问或建议,欢迎在评论区留言讨论。
相关文章:
【深入C++】map和set的使用
文章目录 C 中的容器分类1. 顺序容器2. 关联容器3. 无序容器4. 容器适配器5. 字符串容器6. 特殊容器 set1.构造函数2.迭代器3.容量相关的成员函数4.修改器类的成员函数5.容器相关操作的成员函数 multiset1.equal_range map1.初始化相关的函数2.迭代器3.容量相关的成员函数4.访问…...
跟代码执行流程,读Megatron源码(二)训练入口pretrain_gpt.py
Megatron-LM默认支持GPT、T5、BERT等多个常见模型的预训练,当下大模型流行,故以pretrain_gpt.py为例做源码的走读。 一. 启动pretrain_gpt.py pretrain_gpt.py为GPT类模型的训练入口,它通过命令行形式被调用,其精确执行路径位于M…...
MATLAB练习题——矩阵(2)
逻辑运算 a [5 0.2 0 -8 -0.7 ],在进行逻辑运算时,a 相当于什么样的逻辑量。 相当于 a[1 1 0 1 1] 角度运算 在 sin(x)运算中,x 是角度还是弧度? 在 sin(x)运算中,x 是弧度,MATLAB 规定所有…...
arm、AArch64、x86、amd64、x86_64 的区别
arm vs AArch64 vs amd64 vs x86_64 vs x86 的区别 当涉及到 CPU 的时候,有许多术语:AArch64、x86_64、amd64、arm 等等。了解它们是什么以及它们之间的区别。 当你查看数据表或软件下载页面时是否被 ARM、AArch64、x86_64、i386 等术语混淆?…...
【SpringBoot】 jasypt配置文件密码加解密
目前我们对yml配置文件中的密码都是明文显示,显然这不安全,有的程序员离职了以后可能会做一些非法骚操作,所以我们最好要做一个加密,只能让领导架构师或者技术经理知道这个密码。所以这节课就需要来实现一下。 我们可以使用jasypt…...
复杂网络的任意子节点的网络最短距离
复杂网络的任意子节点的网络最短距离 题目要求介绍 本文算法测试用的数据集为空手道俱乐部,其中空手道俱乐部的数据集可通过这个链接进行下载•http://vlado.fmf.uni-lj.si/pub/networks/data/Ucinet/UciData.htm#zachary 摘要 本文旨在解决复杂网络中任意子节点…...
(Qt) 文件读写基础
文章目录 🗂️前言📄ref📄访问标记🗃️enum 标记 🗂️Code📄demo📄分点讲解🗃️继承体系🗃️打开/关闭🗃️写🗃️读 🗂️END…...
全产业布局对穿戴甲品牌连锁店的意义
对于美甲行业来说,穿戴甲虽然不是什么新生事物,但也就是近两年才流行开来。面对井喷的市场需求,相应的从业者,不管是品牌连锁店,还是做批发、外贸,美甲周边、亦或是OEM的,大家都忙得不亦乐乎&am…...
git的一些使用技巧(git fetch 和 git pull的区别,git merge 和 git rebase的区别)
最近闲来无聊,虽然会使用git操作,但是 git fetch 和 git pull 的区别,git merge 和 git rebase的区别只是一知半解,稍微研究一下; git fetch 和 git pull 的区别 git fetch git fetch 是将远程仓库中的改动拉到本地…...
展厅中控系统有哪些优势呢
格芬科技的展厅中控系统具有多方面的优势,主要体现在以下几个方面: 一、高度集成与灵活控制 全终端网络可编程:格芬科技的展厅中控系统采用全终端网络可编程技术,能够实现对展厅内各种设备的集中控制和管理,包括电脑…...
FPGA开发在verilog中关于阻塞和非阻塞赋值的区别
一、概念 阻塞赋值:阻塞赋值的赋值号用“”表示,对应的是串行执行。 对应的电路结构往往与触发沿没有关系,只与输入电平的变化有关系。阻塞赋值的操作可以认为是只有一个步骤的操作,即计算赋值号右边的语句并更新赋值号左边的语句…...
动态特征转换的艺术:在Mojo模型中实现自定义变换的策略
动态特征转换的艺术:在Mojo模型中实现自定义变换的策略 在机器学习中,特征转换是数据预处理的关键步骤,它直接影响模型的性能和结果的准确性。Mojo模型,作为一种高效的模型部署形式,允许在不同环境中运行模型并进行预…...
如何让Python爬虫在遇到异常时继续运行
概述 在数据收集和数据挖掘中,爬虫技术是一项关键技能。然而,爬虫在运行过程中不可避免地会遇到各种异常情况,如网络超时、目标网站变化、数据格式不一致等。如果不加以处理,这些异常可能会导致爬虫程序中断,影响数据…...
手把手带你搭建Snort入侵检测系统
在当今数字化社会,网络安全问题日益突出。为了有效防范网络攻击,部署入侵检测系统(IDS)是必要的防护措施。Snort作为一款功能强大的开源IDS工具,被广泛应用于各种网络环境中。本文将手把手教您如何从零开始实现Snort入…...
小程序内嵌uniapp页面跳转回小程序指定页面方式
使用微信小程序提供的Api:wx.miniProgram.navigateTo 在小程序中嵌套uniapp的H5页面,并使用wx.miniProgram.navigateTo进行页面跳转,需要确保满足以下条件: 你的小程序必须是通过uniapp构建的,并且支持小程序嵌套。 你…...
基于 Three.js 的 3D 模型加载优化
作者:来自 vivo 互联网前端团队- Su Ning 作为一个3D的项目,从用户打开页面到最终模型的渲染需要经过多个流程,加载的时间也会比普通的H5项目要更长一些,从而造成大量的用户流失。为了提升首屏加载的转化率,需要尽可能…...
Jlink下载与适配keil ccs theia教程 用jlink代替ti自己的下载仿真器
用jlink代替ti自己的下载仿真器,然后你去买立创的m0g3507才19.9包赚160 安装 J-Link 软件包 J-Link 软件包 v7.88i 或更高版本支持 MSPM0。 从 Segger 网站下载安装程序 按照安装程序说明操作 安装程序将自动请求更新 IAR 或 Keil(如果已安装&#x…...
C# 进制之间的转换(二进制,八进制,十进制,十六进制)
常用的方法是:Convert.ToString(byte value, int toBase), 并且有多个重载方法, value的类型可以为short,int 等,但必须是整数且不能为负数, 一般默认为十进制 toBase: 返回值的基数,必须是 2、…...
Linux 基础开发工具 : Vim编辑器
Vim 是 Linux 和其他类 Unix 系统上广泛使用的文本编辑器之一。它基于更早的 vi 编辑器,但添加了许多增强功能和扩展。Vim 是“Vi IMproved”的缩写,意为“改进的 Vi”,我们常使用Vim编辑器编写c/c代码。 ps:该篇介绍均为最基础介…...
Delphi 11.2 配置Android SDK 环境
打开 Delphi 11 点击 Tools–Options… 然后点击 Deployment–SDK Manager–Add… 这里如果配置64位就选 Android 64-bit,如果配置32位就选 Android 32-bit 点击 Select an SDK version–Add New… 有警告图标的就是有问题的项,需要手动更新一下…...
19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式
今天是关于AI如何在教学中增强学生的学习体验,我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育,这并非炒作,而是已经发生的巨大变革。教育机构和教育者不能忽视它,试图简单地禁止学生使…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...
