C++ 关联式容器:map,multimap,set,multiset

article/2025/8/15 6:00:47

目录

引言

一、关联式容器概述

1.1 与序列式容器的区别

1.2 底层结构

二、set容器详解set介绍

2.1 set的特性

2.2 set的模板参数

2.3 set的常用接口

2.4 set使用示例

三、map容器详解map介绍

3.1 map的特性

3.2 map的模板参数

3.3 map的常用接口

3.4 map使用示例

四、multiset容器详解multiset介绍 ​

4.1 multiset的特性 ​

4.2 multiset的模板参数 

4.3 multiset的常用接口 

  4.4 multiset使用示例 

五、multimap容器详解multimap介绍 

​编辑5.1 multimap的特性 ​

5.2 multimap的模板参数 

5.3 multimap的常用接口 

 5.4 multimap使用示例 

六、总结


引言

在C++ 的标准模板库(STL)中,关联式容器是非常重要的一部分,它们为我们提供了高效的数据存储和检索方式。今天,我们就来深入探讨一下其中的  map  和  set  容器,看看它们是如何在实际编程中发挥作用的。

一、关联式容器概述

1.1 与序列式容器的区别

在之前的学习中,我们接触过像  vector 、 list 、 deque  这样的序列式容器,它们底层是线性序列的数据结构,存储的是数据本身。而关联式容器存储的是  <key, value>  结构的键值对,在数据检索时比序列式容器效率更高。

1.2 底层结构

关联式容器根据应用场景不同,主要有树形结构(如红黑树)和哈希结构。今天重点讨论的  map  和  set  以及它们的变体  multimap 、 multiset  底层多采用平衡搜索树(红黑树)实现,这使得容器中的元素是有序的序列。

二、set容器详解set介绍

2.1 set的特性

 set  是按照一定次序存储元素的容器,其中元素的  value  也标识它自己(即  value  就是  key  ),并且每个  value  必须是唯一的。 set  中的元素不能在容器中修改(元素总是  const  ),但可以插入或删除。其内部元素默认按照小于来比较排序。

2.2 set的模板参数

cpptemplate <class T,class Compare = less<T>,class Allocator = allocator<T>> class set;

-  T :存储元素的类型,实际底层存储  <value, value>  的键值对。

-  Compare :比较器类型,默认按小于比较。

-  Allocator :空间配置器,一般不用用户传递。

2.3 set的常用接口

1. 插入元素

cpp#include <set>#include <iostream>int main() {std::set<int> s;std::pair<std::set<int>::iterator, bool> ret = s.insert(5);if (ret.second) {std::cout << "插入成功,元素值为:" << *ret.first << std::endl;} else {std::cout << "插入失败,元素已存在" << std::endl;}return 0;}

1. 删除元素

cpp#include <set>#include <iostream>int main() {std::set<int> s = {1, 2, 3, 4, 5};s.erase(s.find(3)); // 删除值为3的元素for (auto e : s) {std::cout << e << " ";}std::cout << std::endl;return 0;}

1. 查找元素


 

cpp#include <set>#include <iostream>int main() {std::set<int> s = {1, 2, 3, 4, 5};std::set<int>::iterator it = s.find(3);if (it != s.end()) {std::cout << "找到元素:" << *it << std::endl;} else {std::cout << "未找到元素" << std::endl;}return 0;}

2.4 set使用示例

cpp#include <set>#include <iostream>void TestSet() {int array[] = {1, 3, 5, 7, 9, 2, 4, 6, 8, 0, 1, 3, 5, 7, 9, 2, 4, 6, 8, 0};std::set<int> s(array, array + sizeof(array) / sizeof(array[0]));std::cout << "set的大小为:" << s.size() << std::endl;// 正向打印set中的元素std::cout << "正向打印set元素:";for (auto& e : s) {std::cout << e << " ";}std::cout << std::endl;// 使用迭代器逆向打印set中的元素std::cout << "逆向打印set元素:";for (auto it = s.rbegin(); it != s.rend(); ++it) {std::cout << *it << " ";}std::cout << std::endl;// set中值为3的元素出现了几次std::cout << "值为3的元素个数:" << s.count(3) << std::endl;}int main() {TestSet();return 0;}

三、map容器详解map介绍

3.1 map的特性

 map  是关联容器,它按照特定的次序(按照  key  来比较)存储由键值  key  和值  value  组合而成的元素。 key  通常用于排序和唯一地标识元素, value  存储与此键值  key  关联的内容。

3.2 map的模板参数


 

cpptemplate <class Key,class T,class Compare = less<Key>,class Allocator = allocator<pair<const Key, T>>> class map;

-  Key :键值对中  key  的类型。

-  T :键值对中  value  的类型。

-  Compare :比较器类型,默认按  key  小于比较。

-  Allocator :空间配置器。

3.3 map的常用接口

1. 插入元素

cpp#include <map>#include <string>#include <iostream>int main() {std::map<std::string, std::string> m;// 方式一:用pair直接构造键值对插入std::pair<std::map<std::string, std::string>::iterator, bool> ret1 = m.insert(std::pair<std::string, std::string>("apple", "苹果"));if (ret1.second) {std::cout << "插入成功" << std::endl;} else {std::cout << "插入失败,元素已存在" << std::endl;}// 方式二:用make_pair函数构造键值对插入std::pair<std::map<std::string, std::string>::iterator, bool> ret2 = m.insert(std::make_pair("banana", "香蕉"));if (ret2.second) {std::cout << "插入成功" << std::endl;} else {std::cout << "插入失败,元素已存在" << std::endl;}// 方式三:通过operator[]插入m["pear"] = "梨";return 0;}

1. 删除元素

cpp#include <map>#include <string>#include <iostream>int main() {std::map<std::string, std::string> m = {{"apple", "苹果"}, {"banana", "香蕉"}};m.erase("banana");for (const auto& e : m) {std::cout << e.first << " -> " << e.second << std::endl;}return 0;}

1. 查找元素

cpp#include <map>#include <string>#include <iostream>int main() {std::map<std::string, std::string> m = {{"apple", "苹果"}, {"banana", "香蕉"}};std::map<std::string, std::string>::iterator it = m.find("apple");if (it != m.end()) {std::cout << "找到元素:" << it->first << " -> " << it->second << std::endl;} else {std::cout << "未找到元素" << std::endl;}return 0;}

3.4 map使用示例

cpp#include <map>#include <string>#include <iostream>void TestMap() {std::map<std::string, std::string> m;// 向map中插入元素的方式// 将键值对<"peach","桃子">插入map中,用pair直接来构造键值对m.insert(std::pair<std::string, std::string>("peach", "桃子"));// 将键值对<"peach","桃子">插入map中,用make_pair函数来构造键值对m.insert(std::make_pair("banana", "香蕉"));// 借用operator[]向map中插入元素m["apple"] = "苹果";std::cout << "map的大小为:" << m.size() << std::endl;// 用迭代器去遍历map中的元素,可以得到一个按照key排序的序列std::cout << "遍历map元素:" << std::endl;for (const auto& e : m) {std::cout << e.first << " ---> " << e.second << std::endl;}// map中的键值对key一定是唯一的,如果key存在将插入失败auto ret = m.insert(std::make_pair("peach", "桃色"));if (ret.second) {std::cout << "peach,桃色不在map中,已经插入" << std::endl;} else {std::cout << "键值为peach的元素已经存在:" << ret.first->first << " ---> " << ret.first->second << " 插入失败" << std::endl;}// 删除key为"apple"的元素m.erase("apple");if (1 == m.count("apple")) {std::cout << "apple还在" << std::endl;} else {std::cout << "apple被吃了" << std::endl;}}int main() {TestMap();return 0;}

四、multiset容器详解multiset介绍
 

4.1 multiset的特性
 


 multiset  是按照特定顺序存储元素的容器,其中元素是可以重复的。元素的  value  也会标识它(因为  multiset  中本身存储的就是  <value, value>  组成的键值对),元素的值不能在容器中进行修改(元素总是  const  ),但可以从容器中插入或删除。其内部元素默认按照小于来比较排序。
 


4.2 multiset的模板参数
 

cpptemplate <class T,class Compare = less<T>,class Allocator = allocator<T>
> class multiset;


 
 
与  set  的模板参数类似, T  为存储元素的类型, Compare  是比较器, Allocator  是空间配置器 。
 


4.3 multiset的常用接口
 


1. 插入元素
 

cpp#include <multiset>
#include <iostream>int main() {std::multiset<int> ms;ms.insert(3);ms.insert(3);ms.insert(5);for (auto e : ms) {std::cout << e << " ";}std::cout << std::endl;return 0;
}


 
 
1. 删除元素
 

cpp#include <multiset>
#include <iostream>int main() {std::multiset<int> ms = {1, 3, 3, 5};ms.erase(ms.find(3)); // 删除一个值为3的元素for (auto e : ms) {std::cout << e << " ";}std::cout << std::endl;return 0;
}


 
 
4.4 multiset使用示例
 

cpp#include <set>
#include <iostream>void TestMultiset() {int array[] = {2, 1, 3, 9, 6, 0, 5, 8, 4, 7};std::multiset<int> ms(array, array + sizeof(array) / sizeof(array[0]));for (auto& e : ms) {std::cout << e << " ";}std::cout << std::endl;
}int main() {TestMultiset();return 0;
}

五、multimap容器详解multimap介绍
 


5.1 multimap的特性
 


 multimap  是关联式容器,它按照特定的顺序,存储由  key  和  value  映射成的键值对  <key, value>  ,其中多个键值对之间的  key  是可以重复的。通常按照  key  排序和唯一地标识元素, value  存储与  key  关联的内容。


5.2 multimap的模板参数
 

cpptemplate <class Key,class T,class Compare = less<Key>,class Allocator = allocator<pair<const Key, T>>
> class multimap;


 
 
和  map  的模板参数类似, Key  是键的类型, T  是值的类型, Compare  是比较器, Allocator  是空间配置器。
 

5.3 multimap的常用接口
 


1. 插入元素
 

cpp#include <multimap>
#include <string>
#include <iostream>int main() {std::multimap<std::string, std::string> mm;mm.insert(std::make_pair("fruit", "apple"));mm.insert(std::make_pair("fruit", "banana"));for (const auto& e : mm) {std::cout << e.first << " -> " << e.second << std::endl;}return 0;
}


1. 删除元素
 

cpp#include <multimap>
#include <string>
#include <iostream>int main() {std::multimap<std::string, std::string> mm = {{"fruit", "apple"}, {"fruit", "banana"}};mm.erase(mm.find("fruit")); // 删除一个key为"fruit"的键值对for (const auto& e : mm) {std::cout << e.first << " -> " << e.second << std::endl;}return 0;
}


 
5.4 multimap使用示例
 

cpp#include <multimap>
#include <string>
#include <iostream>void TestMultimap() {std::multimap<std::string, std::string> mm;mm.insert(std::make_pair("person", "Alice"));mm.insert(std::make_pair("person", "Bob"));mm.insert(std::make_pair("animal", "cat"));mm.insert(std::make_pair("animal", "dog"));std::cout << "遍历multimap元素:" << std::endl;for (const auto& e : mm) {std::cout << e.first << " ---> " << e.second << std::endl;}
}int main() {TestMultimap();return 0;
}
表格
容器元素唯一性元素修改底层结构应用场景举例
set唯一不可修改红黑树红黑树|存储不重复的整数集合,如学生学号集合
mapkey唯一value可修改红黑树红黑树|存储学生学号与成绩的映射关系
multiset可重复不可修改红黑树统计单词在文本中出现的所有位置(位置可重复)
multimapkey可重复value可修改红黑树|红黑树|存储一个班级中所有学生的成绩(可能有重名学生)

六、总结

 set  和  map  作为C++ STL中重要的关联式容器,有着广泛的应用场景。 set  适用于需要存储唯一元素并进行快速查找、排序的场景; map  则适用于需要建立键值对映射关系,通过  key  高效查找  value  的场景。理解它们的特性、接口和底层实现,能帮助我们在实际编程中更高效地使用它们,优化代码性能。希望通过这篇博客,大家能对  set  和  map  有更深入的认识。


http://www.hkcw.cn/article/oddCBdwMDr.shtml

相关文章

从零开始配置Qt+VsCode环境

从零开始配置QtVsCode环境 文章目录 从零开始配置QtVsCode环境写在前面扩展安装及配置Qt Configure配置 VsCode创建Qt工程VsCodeQMakeMinGwVsCodeQMakeMsvcVsCodeCMakeMinGwVsCodeCMakeMsvcQtCreatorQMakeMinGw->VsCodeQtCreatorQMakeMsvc->VsCodeQtCreatorCMakeMinGw-&g…

Matlab/Simulink - BLDC直流无刷电机仿真基础教程(一) - 三相逆变器的搭建

Matlab/Simulink - BLDC直流无刷电机仿真基础教程&#xff08;一&#xff09; - 三相逆变器的搭建 前言一、BLDC电机六步换相简明控制原理二、Simulink中BLDC电机模块的机械连接三、三相逆变电路的搭建四、仿真参数设置与仿真结果验证五、补充内容参考链接 前言 本系列文章分享…

Lapce:一款用 Rust 编写的快速且强大的代码编辑器

Lapce&#xff08;IPA&#xff1a;/lps/&#xff09;是一个使用纯 Rust 编写的开源代码编辑器。通过利用 OpenGL 渲染 GUI&#xff0c;以及 Rust 提供的性能&#xff0c;采用Xi-Editor的Rope Science设计&#xff0c;可实现闪电般的快速计算。 Stars 数35888Forks 数1113 主要…

SpringBoot启动后初始化的几种方式

目录 一、静态代码块 二、构造方法 三、PostConstruct 四、InitializingBean 接口 五、 Bean 注解中的 initMethod 六、 CommandLineRunner 接口 七、ApplicationRunner 接口 八、EventListener事件 九、SmartInitializingSingleton接口 十、ApplicationListener接口…

【MySQL课程学习】:MySQL安装,MySQL如何登录和退出?MySQL的简单配置

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;MySQL课程学习 &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 目录 MySQL在Centos 7环境下的安装&#xff1a; 卸载…

Node.js下载安装及环境配置教程(保姆级教程)

一、安装程序 &#xff08;安装包放在文章最后需要的友友可自取哦&#xff09; &#xff08;1&#xff09;下载完成后&#xff0c;双击安装包&#xff0c;开始安装Node.js &#xff08;2&#xff09;此位置可修改为自己的安装路径&#xff0c;修改完后点击next &#xff08;3…

com.mysql.cj.jdbc.exceptions.CommunicationsException Communications link failure 问题解决

前言: 一般这个报错大多是网络原因导致的&#xff0c;确保你不是网络问题再往下看 问题 在一个方法上&#xff08;该方法非常复杂执行时间长&#xff09;加了 Transactional(rollbackFor Exception.class)后出现了如下图所示的错误 解决&#xff1a; 经过排查并非网络问…

【解决方案】CloudFront VPC Origins 实践流程深入解析 —— 安全高效架构的实战之道

目录 引言一、VPC Origins 的核心价值&#xff08;一&#xff09;安全性提升&#xff08;二&#xff09;运维效率优化&#xff08;三&#xff09;成本节约&#xff08;四&#xff09;全球分发能力的保留 二、VPC Origins 的架构解析&#xff08;一&#xff09;流量路径设计&…

MySQL性能调优(三):MySQL中的系统库(sys系统库、information_schema)

文章目录 MySQL性能调优数据库设计优化查询优化配置参数调整硬件优化 MySQL中的系统库1.3.sys系统库1.3.1.sys使用须知1.3.2.sys系统库使用1.3.3.查看慢SQL语句慢在哪里1.3.4.小结 1.4.information_schema1.4.1.什么是information_schema1.4.2.information_schema表分类Server层…

MySQL的详细使用教程

目录 1. 连接到MySQL服务器2. 创建和删除数据库2-1创建数据库2-2删除数据库 3. 数据表操作3.1 选择数据库3.2 创建数据表3.3 查询数据表3.4 修改数据表3.5 删除数据表 4. 数据内容操作4.1数据操作1. 插入数据2. 查询数据&#xff08;1&#xff09;like模糊查询&#xff08;%表示…

IDEA编写SpringBoot项目时使用Lombok报错“找不到符号”的原因和解决

目录 概述|背景 报错解析 解决方法 IDEA配置解决 Pom配置插件解决 概述|背景 报错发生背景&#xff1a;在SpringBoot项目中引入Lombok依赖并使用后出现"找不到符号"的问题。 本文讨论在上述背景下发生的报错原因和解决办法&#xff0c;如果仅为了解决BUG不论原…

【中间件】Pulsar集群安装

目录 一、Pulsar介绍 1.1 Pulsar基本介绍 1.2 Pulsar架构 Producer & Consumer Apache Zookeeper Pulsar Brokers Apache Bookkeeper 二、Zookeeper集群安装 三、Pulsar集群安装 3.1 bookie与broker配置 3.1.1 修改bookie配置文件 3.1.2 修改broker配置文件 3…

41-dify案例分享-基于database插件实现Text2sql的数据库查询图表工作流

1 前言 Text2SQL&#xff08;或称NL2SQL&#xff09;是一种自然语言处理技术&#xff0c;旨在将自然语言&#xff08;Natural Language&#xff09;问题转化为关系型数据库中可执行的结构化查询语言&#xff08;Structured Query Language&#xff0c;SQL&#xff09;&#xf…

数据库-MySQL 实战项目——学生选课系统数据库设计与实现(附源码)

一、前言 该项目非常适合MySQL入门学习的小伙伴&#xff0c;博主提供了源码、数据和一些查询语句&#xff0c;供大家学习和参考&#xff0c;代码和表设计有什么不恰当还请各位大佬多多指点。 所需环境 MySQL可视化工具&#xff1a;navicat&#xff1b; 数据库&#xff1a;MySq…

中小型企业大数据平台全栈搭建:Hive+HDFS+YARN+Hue+ZooKeeper+MySQL+Sqoop+Azkaban 保姆级配置指南

目录 背景‌一、环境规划与依赖准备‌1. 服务器规划(3节点集群)2. 系统与依赖‌3. Hadoop生态组件版本与下载路径4. 架构图二、Hadoop(HDFS+YARN)安装与配置‌1. 下载与解压(所有节点)2. HDFS高可用配置3. YARN资源配置‌4. 启动Hadoop集群三、MySQL安装与Hive元数据配置…

从 0~1 保姆级 详细版 PostgreSQL 数据库安装教程

PostgreSQL数据库安装 PostgreSQL官网 【PostgreSQL官网】 | 【PostgreSQL安装官网_Windows】 安装步骤 step1&#xff1a; 选择与电脑相对应的PostgreSQL版本进行下载。 step2&#xff1a; 双击打开刚才下载好的文件。 step3&#xff1a; 在弹出的setup窗口中点击 …

【Spring Boot】网页五子棋项目中遇到的困难及解决方法

目录 一、HikariPool-1 - Starting异常二、Invalid bound statement (not found)异常三、The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary异常四、The server time zone value时区报错异常五、补充知识点…

上海启动3-6岁儿童近视监测 推进视力健康关口前移

6月1日,第30个全国“爱眼日”上海市儿童青少年眼健康主题活动发布了上海市儿童青少年近视率最新监测情况。2024年上海市6-18岁儿童青少年近视率比2023年下降1.5个百分点。为推进近视预防关口前移,上海市眼病防治中心启动了“低龄儿童近视监测与干预服务项目”,聚焦3-6岁近视…

郑钦文首次晋级法网8强 刷新个人最佳战绩

北京时间6月1日晚,在法网女单1/8决赛中,8号种子郑钦文以7-6(5)、1-6、6-3战胜19号种子俄罗斯选手萨姆索诺娃,职业生涯首次跻身法网女单八强,刷新个人赛会最佳战绩。这也是中国选手时隔14年再次闯进法网八强。首盘比赛中,郑钦文两次先被破发但迅速回破,双方战至抢七。最终…

新势力5月销量榜解读 零跑三连冠

零跑汽车再次夺得新势力月销量冠军。6月1日,各大造车新势力发布了5月份的交付数据。零跑汽车连续三个月稳居榜首,鸿蒙智行和理想汽车分别位列第二、第三,销量均重回4万辆。整体来看,5月车市进一步回暖,尤其是极氪获得了最高的环比增速,达37.74%。5月,零跑汽车全系交付再…