C++—— set、map、multiset、multimap的介绍及使用
目录
关联式容器
关联式容器的特点和使用场景
树形结构与哈希结构
树形结构
哈希结构
键值对
set
set的介绍
set的定义方式
set的使用
multiset
map
map的介绍
map的定义方式
map的使用
multimap
关联式容器
C++标准模板库(STL)中的关联式容器(Associative Containers)是一类根据键值对元素进行存储和操作的数据结构。它们允许快速查找、插入和删除操作,并且通常是基于树或哈希表实现的。C++ STL中的关联式容器包括四种主要类型:
-
std::set
和std::multiset
:std::set
是一种集合,其中每个元素是唯一的,按特定顺序排序。std::multiset
与std::set
类似,但允许重复元素。- 这两种容器通常使用红黑树等平衡二叉搜索树实现,因此其查找、插入和删除操作的时间复杂度为 O(log n)。
-
std::map
和std::multimap
:std::map
是一种关联数组,其中每个元素都是一个键-值对,键是唯一的,按特定顺序排序。std::multimap
与std::map
类似,但允许键重复。- 这两种容器也通常使用平衡二叉搜索树实现,其查找、插入和删除操作的时间复杂度同样为 O(log n)。
-
std::unordered_set
和std::unordered_multiset
:std::unordered_set
是一种无序集合,其中每个元素是唯一的,元素无特定顺序。std::unordered_multiset
与std::unordered_set
类似,但允许重复元素。- 这两种容器使用哈希表实现,因此其平均情况下的查找、插入和删除操作时间复杂度为 O(1)。
-
std::unordered_map
和std::unordered_multimap
:std::unordered_map
是一种无序关联数组,其中每个元素是一个键-值对,键是唯一的,元素无特定顺序。std::unordered_multimap
与std::unordered_map
类似,但允许键重复。- 这两种容器也使用哈希表实现,其平均情况下的查找、插入和删除操作时间复杂度为 O(1)。
关联式容器的特点和使用场景
-
有序关联容器(
set
、multiset
、map
、multimap
):- 排序:元素按照键的顺序排列,可以方便地进行范围查询。
- 使用场景:需要按顺序访问元素或进行范围查询时,例如实现有序字典或集合。
-
无序关联容器(
unordered_set
、unordered_multiset
、unordered_map
、unordered_multimap
):- 无序:元素无特定顺序,通过哈希值快速访问。
- 使用场景:关注查找、插入和删除的平均时间效率,而不在乎元素顺序时,例如实现哈希表或快速查找的数据结构。
树形结构与哈希结构
树形结构
树形结构常用于实现有序关联容器,如 std::set
、std::multiset
、std::map
和 std::multimap
。具体来说,这些容器通常采用平衡二叉搜索树(如红黑树)来实现。以下是树形结构的一些关键点:
- 自动排序:元素按键值自动排序,支持有序遍历。
- 平衡性:红黑树等平衡二叉树保证了树的高度在O(log n)范围内,从而确保查找、插入和删除操作的时间复杂度为O(log n)。
- 复杂性:相对于哈希表实现,树形结构的插入和删除操作更为复杂,需要维护树的平衡。
适用场景
- 需要按顺序访问或处理数据,例如范围查询。
- 需要查找键的前驱或后继等顺序关系操作。
哈希结构
哈希结构用于实现无序关联容器,如 std::unordered_set
、std::unordered_multiset
、std::unordered_map
和 std::unordered_multimap
。这些容器基于哈希表来实现。以下是哈希结构的一些关键点:
- 无序存储:元素无特定顺序,基于哈希值进行存储。
- 快速访问:平均情况下,查找、插入和删除操作的时间复杂度为O(1)。
- 哈希冲突:需要处理哈希冲突,一般采用链地址法或开放地址法等策略。
适用场景
- 更关注操作的平均时间效率,而不在乎元素的顺序。
- 大量频繁的查找、插入和删除操作,例如实现哈希表或集合。
键值对
键值对是用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息。
比如我们若是要建立一个英译汉的字典,那么该字典中的英文单词与其对应的中文含义就是一一对应的关系,即通过单词可以找到与其对应的中文含义。
在SGI-STL中关于键值对的定义如下:
template <class T1, class T2>
struct pair
{typedef T1 first_type;typedef T2 second_type;T1 first;T2 second;pair() : first(T1()), second(T2()){}pair(const T1& a, const T2& b) : first(a), second(b){}
};
set
set的介绍
1.set是按照一定次序存储元素的容器,使用set的迭代器遍历set中的元素,可以得到有序序列。
2.set当中存储元素的value都是唯一的,不可以重复,因此可以使用set进行去重。
3.与map/multimap不同,map/multimap中存储的是真正的键值对<key, value>,set中只放value,但在底层实际存放的是由<value, value>构成的键值对,因此在set容器中插入元素时,只需要插入value即可,不需要构造键值对。
4.set中的元素不能被修改,因为set在底层是用二叉搜索树来实现的,若是对二叉搜索树当中某个结点的值进行了修改,那么这棵树将不再是二叉搜索树。
5.在内部,set中的元素总是按照其内部比较对象所指示的特定严格弱排序准则进行排序。当不传入内部比较对象时,set中的元素默认按照小于来比较。
6.set容器通过key访问单个元素的速度通常比unordered_set容器慢,但set容器允许根据顺序对元素进行直接迭代。
7.set在底层是用平衡搜索树(红黑树)实现的,所以在set当中查找某个元素的时间复杂度为logN。
set的定义方式
方式一: 构造一个某类型的空容器。
set<int> s1; //构造int类型的空容器
方式二: 拷贝构造某类型set容器的复制品。
set<int> s2(s1); //拷贝构造int类型s1容器的复制品
方式三: 使用迭代器拷贝构造某一段内容。
string str("abcdef");
set<char> s3(str.begin(), str.end()); //构造string对象某段区间的复制品
方式四: 构造一个某类型的空容器,比较方式指定为大于。
set < int, greater<int>> s4; //构造int类型的空容器,比较方式指定为大于
set的使用
set当中常用的成员函数如下:
set当中迭代器相关函数如下:
使用示例:
#include <iostream>
#include <set>int main() {// 创建一个整数类型的set容器std::set<int> mySet;// 插入一些元素到set中mySet.insert(5);mySet.insert(3);mySet.insert(8);mySet.insert(2);// 使用迭代器遍历容器并输出元素(正向遍历)std::cout << "使用迭代器正向遍历容器:" << std::endl;for (auto it = mySet.begin(); it != mySet.end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;// 删除一个元素mySet.erase(3);// 使用范围 for 循环遍历容器并输出元素std::cout << "使用范围 for 循环正向遍历容器:" << std::endl;for (const auto& elem : mySet) {std::cout << elem << " ";}std::cout << std::endl;// 检查集合中是否包含特定元素int target = 8;if (mySet.count(target)) {std::cout << "集合包含 " << target << std::endl;} else {std::cout << "集合不包含 " << target << std::endl;}// 获取集合的大小std::cout << "集合的大小:" << mySet.size() << std::endl;// 清空集合mySet.clear();// 检查集合是否为空if (mySet.empty()) {std::cout << "集合为空" << std::endl;} else {std::cout << "集合不为空" << std::endl;}// 向空集合中插入一些元素mySet.insert(10);mySet.insert(20);mySet.insert(30);// 使用反向迭代器遍历容器并输出元素(反向遍历)std::cout << "使用反向迭代器反向遍历容器:" << std::endl;for (auto rit = mySet.rbegin(); rit != mySet.rend(); ++rit) {std::cout << *rit << " ";}std::cout << std::endl;return 0;
}
multiset
multiset容器与set容器的底层实现一样,都是平衡搜索树(红黑树),其次,multiset容器和set容器所提供的成员函数的接口都是基本一致的,这里就不再列举了,multiset容器和set容器的唯一区别就是,multiset允许键值冗余,即multiset容器当中存储的元素是可以重复的。
#include <iostream>
#include <set>int main() {// 创建一个允许重复元素的 multiset 容器std::multiset<int> ms;// 插入一些元素到 multiset 中ms.insert(1);ms.insert(4);ms.insert(3);ms.insert(3);ms.insert(2);ms.insert(2);ms.insert(3);// 使用范围 for 循环遍历容器并输出元素for (auto e : ms) {std::cout << e << " ";}std::cout << std::endl; // 输出:1 2 2 3 3 3 4return 0;
}
由于multiset容器允许键值冗余,因此两个容器中成员函数find和count的意义也有所不同:
map
map的介绍
1.map是关联式容器,它按照特定的次序(按照key来比较)存储键值key和值value组成的元素,使用map的迭代器遍历map中的元素,可以得到有序序列。
2.在map中,键值key通常用于排序和唯一地标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型value_type绑定在一起,并取别名为pair。
3.map容器中元素的键值key不能被修改,但是元素的值value可以被修改,因为map底层的二叉搜索树是根据每个元素的键值key进行构建的,而不是值value。
4.在内部,map中的元素总是按照键值key进行比较排序的。当不传入内部比较对象时,map中元素的键值key默认按照小于来比较。
5.map容器通过键值key访问单个元素的速度通常比unordered_map容器慢,但map容器允许根据顺序对元素进行直接迭代。
6.map容器支持下标访问符,即在[]中放入key,就可以找到与key对应的value。
7.map在底层是用平衡搜索树(红黑树)实现的,所以在map当中查找某个元素的时间复杂度为logN。
map的定义方式
方式一: 指定key和value的类型构造一个空容器。
map<int, double> m1; //构造一个key为int类型,value为double类型的空容器
方式二: 拷贝构造某同类型容器的复制品。
map<int, double> m2(m1); //拷贝构造key为int类型,value为double类型的m1容器的复制品
方式三: 使用迭代器拷贝构造某一段内容。
map<int, double> m3(m2.begin(), m2.end()); //使用迭代器拷贝构造m2容器某段区间的复制品
方式四: 指定key和value的类型构造一个空容器,key比较方式指定为大于。
map<int, double, greater<int>> m4; //构造一个key为int类型,value为double类型的空容器,key比较方式指定为大于
map的使用
map的插入 map的查找 map的删除 map的[ ]运算符重载 map的迭代器
#include <iostream>
#include <map>int main() {// 创建一个键为整数,值为字符串的 map 容器std::map<int, std::string> myMap;// 插入元素到 map 中myMap.insert(std::make_pair(1, "One"));myMap.insert(std::make_pair(2, "Two"));myMap.insert(std::make_pair(3, "Three"));// 查找 map 中的元素int keyToFind = 2;auto it = myMap.find(keyToFind);if (it != myMap.end()) {std::cout << "键为 " << keyToFind << " 的值为:" << it->second << std::endl;} else {std::cout << "键为 " << keyToFind << " 的元素未找到" << std::endl;}// 删除 map 中的元素int keyToDelete = 1;myMap.erase(keyToDelete);// 使用 [] 运算符向 map 中插入或访问元素myMap[4] = "Four";// 使用迭代器遍历 map 并输出键值对std::cout << "遍历 map:" << std::endl;for (auto it = myMap.begin(); it != myMap.end(); ++it) {std::cout << "键:" << it->first << " 值:" << it->second << std::endl;}return 0;
}
map的其他成员函数
除了上述成员函数外,map当中还有如下几个常用的成员函数:
#include <iostream>
#include <string>
#include <map>int main() {// 创建一个 map 容器,键为整数,值为字符串std::map<int, std::string> myMap;// 插入一些键值对到 map 中myMap.insert(std::make_pair(2, "two"));myMap.insert(std::make_pair(1, "one"));myMap.insert(std::make_pair(3, "three"));// 获取容器中元素的个数std::cout << "容器中元素的个数:" << myMap.size() << std::endl; // 输出:3// 容器中 key 值为 2 的元素个数std::cout << "容器中 key 值为 2 的元素个数:" << myMap.count(2) << std::endl; // 输出:1// 清空容器myMap.clear();// 容器判空std::cout << "容器是否为空:" << myMap.empty() << std::endl; // 输出:1// 创建一个临时的 map 容器,并交换数据std::map<int, std::string> tmpMap;myMap.swap(tmpMap);return 0;
}
multimap
multimap容器与map容器的底层实现一样,也都是平衡搜索树(红黑树),其次,multimap容器和map容器所提供的成员函数的接口都是基本一致的,这里也就不再列举了,multimap容器和map容器的区别与multiset容器和set容器的区别一样,multimap允许键值冗余,即multimap容器当中存储的元素是可以重复的。
#include <iostream>
#include <string>
#include <map>int main() {// 创建一个 multimap 容器,键为整数,值为字符串std::multimap<int, std::string> mm;// 插入一些键值对到 multimap 中(允许重复键)mm.insert(std::make_pair(2, "two"));mm.insert(std::make_pair(2, "double"));mm.insert(std::make_pair(1, "one"));mm.insert(std::make_pair(3, "three"));// 使用范围 for 循环遍历 multimap 并输出键值对for (const auto& e : mm) {std::cout << "<" << e.first << "," << e.second << "> ";}std::cout << std::endl; // 输出:<1,one> <2,two> <2,double> <3,three>return 0;
}
由于multimap容器允许键值冗余,因此两个容器中成员函数find和count的意义也有所不同:
其次,由于multimap容器允许键值冗余,调用[ ]运算符重载函数时,应该返回键值为key的哪一个元素的value的引用存在歧义,因此在multimap容器当中没有实现[ ]运算符重载函数。
相关文章:

C++—— set、map、multiset、multimap的介绍及使用
目录 关联式容器 关联式容器的特点和使用场景 树形结构与哈希结构 树形结构 哈希结构 键值对 set set的介绍 set的定义方式 set的使用 multiset map map的介绍 map的定义方式 map的使用 multimap 关联式容器 C标准模板库(STL)中的关联…...

STM32 学习——1. STM32最小系统
这是一个最小系统的测试,LED灯会进行闪烁。选用PC13口,因为STM32F103C8T6 硬件开发板中,这个端口是一个LED 1. proteus8.15 原理图 2. cubemx 新建工程 3. keil 代码 while (1){HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);HAL_Delay(100);…...

react实现table可拖拽表头(给react-jss样式传递参数、滚动条样式)
目录 react实现table可拖拽表头安装依赖resizableTitle / index.tsxdrapTable.tsx使用DragTable 组件滚动条样式效果 react实现table可拖拽表头 安装依赖 yarn add react-resizable yarn add react-jssresizableTitle / index.tsx import { createUseStyles } from react-js…...

如何跨过robots协议的限制爬取内容?
在讨论如何“跨过robots协议的限制爬取内容”之前,重要的是强调遵循网络礼仪和法律法规的必要性。robots协议(Robots Exclusion Standard)是网站所有者向网络爬虫(包括搜索引擎和其他自动化工具)传达其爬取意愿的一种方…...

Parasoft C++Test软件静态分析操作指南_编码规范/标准检查
系列文章目录 Parasoft CTest软件安装指南 Parasoft CTest软件静态分析操作指南_编码规范/标准检查 Parasoft CTest软件静态分析操作指南_软件质量度量 Parasoft CTest软件静态分析_自动提取静态分析数据生成文档 Parasoft CTest软件单元测试_操作指南 Parasoft CTest软件单元…...

[AIGC] CompletableFuture如何实现任务链式调用?
Java 中的 CompletableFuture 提供了多种方法来支持任务链式调用。这些方法允许你将一组操作链接在一起,形成一个任务链,每一个任务只有在上一个任务成功完成后才会被执行。现在,我们来看一下一些常用的链接任务的方法: thenAppl…...

神奇动物在哪里?斯洛文尼亚旅游之野生动物寻踪
不仅拥有优美动人的自然风光,斯洛文尼亚还以其丰富的生物多样性而闻名。得益于国家对大自然开展的保护工作,斯洛文尼亚超过三分之一的国土面积都被规划为保护区,拥有约1.5万种动物和6000种植物,其中不乏众多特有、稀有和濒危动植物…...

电商项目之有趣的支付签名算法
文章目录 1 问题背景2 思路3 代码实现 1 问题背景 在发起支付的时候,一般都需要对发送的请求参数进行加密或者签名,下文简称这个过程为“签名”。行业内比较普遍的签发算法有: (1)按支付渠道给定的字段排序进行拼接&am…...

Web开发核心
文章目录 1.http协议简介2.http协议特性3.http请求和响应协议4.最简单的Web程序5.基于flask搭建web⽹站6.浏览器开发者⼯具(重点) 1.http协议简介 HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于 万维网(WWW:Norld W…...

【Python】【Scrapy 爬虫】理解HTML和XPath
为了从网页中抽取信息,必须对其结构有更多了解。我们快速浏览HTML、HTML的树状表示,以及在网页上选取信息的一种方式XPath。 HTML、DOM树表示以及XPath 互联网是如何工作的? 当两台电脑需要通信的时候,你必须要连接他们ÿ…...

【CTF Web】CTFShow web5 Writeup(SQL注入+PHP+位运算)
web5 1 阿呆被老板狂骂一通,决定改掉自己大意的毛病,痛下杀手,修补漏洞。 解法 注意到: <!-- flag in id 1000 -->拦截很多种字符,连 select 也不给用了。 if(preg_match("/\|\"|or|\||\-|\\\|\/|\…...

LeetCode 968.监控二叉树 (hard)
968.监控二叉树 力扣题目链接(opens new window) 给定一个二叉树,我们在树的节点上安装摄像头。 节点上的每个摄影头都可以监视其父对象、自身及其直接子对象。 计算监控树的所有节点所需的最小摄像头数量。 贪心思路: 从下往上看,局部最…...

数理逻辑:1、预备知识
17.1 命题和联结词 命题:可以判定真假的陈述句。(则悖论,祈使句,疑问句都不是命题) 原子命题:不能被分割为更小的命题的命题 例如: 2既是素数又是偶数 可以由$p: 2 是素数,…...

14-云原生监控体系-Redis_exporter 监控 MySQL[部署Dashborad告警规则实战]
文章目录 环境准备切片集群主从哨兵1. 部署1.1. 二进制方式1.1.1. 下载二进制包1.1.2. 部署1.2. docker-compose 容器方式1.3. 配置连接&认证参数1.3.1. 连接认证参数1.3.2. 配置服务控制 systemd2. 配置到 Prometheus3 Dashboard4. 告警规则...

DOS学习-目录与文件应用操作经典案例-xcopy
新书上架~👇全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 目录 一.前言 二.使用 三.案例 一.前言 xcopy命令是DOS系统中一个强大的文件和目录复制工具&…...

Midjourney是一个基于GPT-3.5系列接口开发的免费AI机器人
Midjourney是一个基于GPT-3.5系列接口开发的免费AI机器人,旨在提供多领域的智能对话服务。Midjourney在不同领域中有不同的定义和应用,以下是对其中两个主要领域的介绍: Midjourney官网:https://www.midjourney.com/ 一、AI绘画工…...

v-model详解
目录 原理 作用 表单类组件封装 编辑v-model简化代码 原理 v-model本质上是一个语法糖。例如应用在输入框上,就是value属性和input属性的合写。 作用 提供数据的双向绑定。 数据变,视图跟着变:value视图变,数据跟着变input 注意&…...
ArcGIS中分割与按属性分割的区别
1、分割ArcGIS批量导出各个市的县级行政边界 视频教学: ArcGIS批量导出各个市的县级行政边界002 2、ArcGIS批量导出全国各省的边界 视频教学: ArcGIS导出全国各省的边界003 推荐学习: ArcGIS全系列实战视频教程——9个单一课程组合系列直播回…...

就业班 第三阶段(ELK) 2401--5.20 day1 ELK 企业实战 ES+head+kibana+logstash部署(最大集群)
ELKkafkafilebeat企业内部日志分析系统 1、组件介绍 1、Elasticsearch: 是一个基于Lucene的搜索服务器。提供搜集、分析、存储数据三大功能。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的ÿ…...

PCM和QAM
PCM(脉冲编码调制)和QAM(正交振幅调制)是两种不同的信号调制技术,它们在通信系统中有着不同的应用和特点。 PCM(脉冲编码调制) 概述 PCM是一种数字信号处理技术,用于将模拟信号转…...

Mongodb分布式id
1、分布式id使用场景 分布式ID是指在分布式系统中用于唯一标识每个元素的数字或字符串。在分布式系统中,各个节点或服务可能独立运行在不同的服务器、数据中心或地理位置,因此需要一种机制来确保每个生成的ID都是全局唯一的,以避免ID冲突。 …...

AI模型抉择:开源VS闭源,谁主沉浮?
AI模型抉择:开源VS闭源,谁主沉浮? 😄生命不息,写作不止 🔥 继续踏上学习之路,学之分享笔记 👊 总有一天我也能像各位大佬一样 🏆 博客首页 怒放吧德德 To记录领地 &am…...

佩戴安全头盔监测识别摄像机
佩戴安全头盔是重要的安全措施,尤其在工地、建筑工程和工业生产等领域,安全头盔的佩戴对于工人的生命安全至关重要。为了更好地管理和监控佩戴安全头盔的情况,监测识别摄像机成为了一项重要的工具。监测识别摄像机可以通过智能技术监测并记录…...

5.24学习记录
[FSCTF 2023]ez_php2 比较简单的pop链 <?php highlight_file(__file__); Class Rd{public $ending;public $cl;public $poc;public function __destruct(){echo "All matters have concluded";die($this->ending);}public function __call($name, $arg){for…...

创建FreeRTOS工程
创建STM32CubeMX工程 配置时钟 配置FreeRTOS 生成Keil MDK的工程 打开工程 结尾 这就是我们用STM32CubeMX创建的最基本的一个FreeRTOS的工程。可以看到,这个与我们使用stm32开发的裸机程序有相同的地方,也有不同的地方,我们可以发现&am…...

HTML中 video标签样式铺满全屏
video标签默认不是铺满的,即使手动设置宽高100%也不会生效,所以当需要video铺满div时,需要加上一个css样式 <videocontrolsstyle"width: 100%; height: 100%; object-fit: fill"autoplay:src"item.video" ></v…...

vue项目移动端商场
一、项目前端页面展示 二、项目整体目录结构 三、项目流程 1. vue快速创建基础项目 创建项目 vue create hk-shop 1 选择需要的配置 创建基础文件夹目录 src文件夹下文件夹目录: ① views 文件夹存放界面 ② components 文件夹存放界面中局部组件 ③ config 文件夹存…...

Golang | Leetcode Golang题解之第97题交错字符串
题目: 题解: func isInterleave(s1 string, s2 string, s3 string) bool {n, m, t : len(s1), len(s2), len(s3)if (n m) ! t {return false}f : make([]bool, m 1)f[0] truefor i : 0; i < n; i {for j : 0; j < m; j {p : i j - 1if i >…...

2024电工杯B题:大学生平衡膳食食谱的优化设计及评价
问题重述 大学时代是学知识长身体的重要阶段,同时也是良好饮食习惯形成的重要时期。这一特定年龄段的年轻人,不仅身体发育需要有充足的能量和各种营养素,而且繁重的脑力劳动和较大量的体育锻炼也需要消耗大量的能源物质。大学生中饮食结构不…...

齐护K210系列教程(三十二)_在线模型训练
在线模型训练 概念理解准备工作1 采集图像1.1 图像要求1.2 使用K210采集图片 2 标注图像3 打包数据集4 上传数据4.1创建项目4.1.1图像分类创建项目4.1.2图像检测创建项目 4.2上传数据4.2.1分类检测上传数据4.2.2图像检测上传数据 5 训练模型6 部署模型以及测试7 测试效果7.1图像…...