当前位置: 首页 > news >正文

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

目录

引言

一、关联式容器概述

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  有更深入的认识。

相关文章:

  • yarn npm pnpm
  • 如何快速分享服务器上的文件
  • 详解多协议通信控制器
  • 【字节拥抱开源】字节豆包团队开源首发 Seed-Coder 大模型
  • 04 mysql 修改端口和重置root密码
  • 软件测试——用例篇(3)
  • Web3 初学者学习路线图
  • 20250510-查看 Anaconda 配置的镜像源
  • navicat112_premium_cs_x64.exe PatchNavicat.exe
  • BeanPostProcessor和AOP
  • 前端SSE技术详解:从入门到实战的完整指南
  • Anaconda的简单使用
  • Java 中的数据类型误导点!!!
  • [Spring AOP 7] 动态通知调用
  • OSCP - Proving Grounds - EvilBox-One
  • 《深入理解Linux网络》笔记
  • 基于语言模型的依存关系分句 和 主题变换检测(基于词频和句段得分)的 意思
  • JavaScript基础-全局作用域
  • 内存、磁盘、CPU区别,Hadoop/Spark与哪个联系密切
  • Hadoop 2.x设计理念解析
  • 邯郸一酒店办婚宴发生火灾,新郎母亲:饭没吃成酒店还要收费
  • 2025上海十大动漫IP评选活动启动
  • 独家丨刘家琨获普利兹克奖感言:守护原始的感悟力
  • 人民时评:透过上海车展读懂三组密码
  • 本科生已发14篇SCI论文被指由其教授父亲挂名,重庆大学成立工作组核实
  • 公募基金改革八大要点:建立浮动管理费收取机制、降低规模排名考核权重