【C++高阶】探索STL的瑰宝 map与set:高效数据结构的奥秘与技巧

news2024/11/27 11:53:30

📝个人主页🌹:Eternity._
⏩收录专栏⏪:C++ “ 登神长阶 ”
🤡往期回顾🤡:初步了解 二叉搜索树
🌹🌹期待您的关注 🌹🌹

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

❀map与set

  • 📒1. 关联式容器
  • 📙2. 键值对
  • 📕3. 树形结构的关联式容器
  • 📜4. set 与 multiset
    • 🎩set的概念
    • 🎈multiset的概念
    • 🧩set的使用
      • 🌈set的模板参数列表
      • 🌞set的构造
      • 🌙set的迭代器
      • ⭐set的其他函数操作
  • 📚5. map 与 multimap
    • 🎩map的概念
    • 🎈multimap的概念
    • 🧩map的使用
      • 🌈map的模板参数说明
      • 🌞map的构造
      • 🌙map的迭代器
      • ⭐map的其他函数操作
  • 📖6. 总结拓展
    • 💧在实际中的应用
    • 🔥总结


前言: 在编程的世界里,数据结构的选择往往决定了程序的效率和稳定性。而在C++的STL(Standard Template Library)库中,map和set无疑是两颗璀璨的瑰宝。它们以其独特的数据存储和检索方式,为我们提供了高效且有序的键值对存储和集合管理方案

mapset不仅拥有自动排序的特性,还提供了丰富的成员函数和迭代器接口,使得我们可以轻松地对其进行操作和管理。无论是在算法竞赛中,还是在日常编程中,它们都是不可或缺的工具

我们将从map和set的定义和特性开始,介绍它们的基本用法和常用成员函数。接着,我们将通过示例代码,展示如何在实际编程中使用它们。同时,我们还将探讨一些常见的错误用法和注意事项,帮助你避免在使用map和set时遇到坑

让我们一起踏上学习 mapset 的旅程,探索它带来的无尽可能!


📒1. 关联式容器

在初阶阶段,我们已经接触过STL中的部分容器,比如:vector、list、deque、
forward_list(C++11)等
,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身

关联式容器(Associative Containers) 是C++标准模板库(STL)中的一类重要容器,主要用于存储和快速检索键值对(key-value pairs)形式的数据。这类容器与序列式容器(如vector、deque、list)的主要区别在于,关联式容器中的元素是按照特定的排序准则(通常是键的大小)进行排序的,从而允许通过键来快速查找、插入和删除元素

关联式容器: 也是用来存储数据的,与序列式容器不同的是,其里面存储的是<key, value>结构的键值对,在数据检索时比序列式容器效率更高


📙2. 键值对

概念: 用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息,比如我们上一篇所提到的kv模型结构 存在对应关系

在这里插入图片描述
在这里插入图片描述

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)
	{}
};

📕3. 树形结构的关联式容器

根据应用场景的不桶,STL总共实现了两种不同结构的管理式容器:树型结构与哈希结构。

  • 树型结构的关联式容器主要有四种:map、set、multimap、multiset
  • 共同点是:使用平衡搜索树(即红黑树)作为其底层结果,容器中的元素是一个有序的序列

关联式容器是C++ STL中一类重要的容器,它们通过键值对的形式存储数据,并支持快速的查找、插入和删除操作。常见的关联式容器包括set、multiset、map和multimap等,它们在不同的应用场景下提供了高效的解决方案


📜4. set 与 multiset

🎩set的概念

概念: set 是 C++ 标准模板库 (STL) 中的一个关联式容器,它包含的元素是唯一的,且默认情况下元素会按照升序排序。set 的内部实现通常使用红黑树来保持其有序性和唯一性

  • set是按照一定次序存储元素的容器
  • 在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的
  • set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们
  • 在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行排序
  • set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对子集进行直接迭代
  • set在底层是用二叉搜索树(红黑树)实现的

特征:

  • 与map/multimap不同,map/multimap中存储的是真正的键值对<key, value>,set中只放value,但在底层实际存放的是由<value, value>构成的键值对
  • set中插入元素时,只需要插入value即可,不需要构造键值对
  • set中的元素不可以重复(因此可以使用set进行去重)
  • 使用set的迭代器遍历set中的元素,可以得到有序序列
  • set中的元素默认按照小于来比较
  • set中查找某个元素,时间复杂度为: l o g 2 n log_2 n log2n
  • set中的元素不允许修改
  • set中的底层使用二叉搜索树(红黑树)来实现

🎈multiset的概念

概念:multiset 是 C++ 标准库 中的一个容器,它允许存储重复的元素。与 set 不同,set 中的元素是唯一的,而 multiset 中的元素可以重复

它与set唯一不同的一点就是 multiset 中的元素可以重复

简单演示一下差别

int main()
{
	int arr[] = { 2, 1, 3, 9, 6, 0, 5, 8, 4, 7 };
	// 注意:multiset在底层实际存储的是<int, int>的键值对
	multiset<int> s(arr, arr + sizeof(arr)/sizeof(arr[0]));
	for (auto& e : s)
	{
		cout << e << " ";
	}
	cout << endl;
	return 0;
}

🧩set的使用

🌈set的模板参数列表

在这里插入图片描述

  • T: set中存放元素的类型,实际在底层存储<value, value>的键值对
  • Compare:set中元素默认按照小于来比较
  • Alloc:set中元素空间的管理方式,使用STL提供的空间配置器管理

🌞set的构造

函数声明功能介绍
set (const Compare& comp = Compare(), const Allocator&= Allocator() )构造空的set
set (InputIterator first, InputIterator last, constCompare& comp = Compare(), const Allocator& =Allocator() )用[first, last)区间中的元素构造set
set ( const set<Key,Compare,Allocator>& x)set的拷贝构造

构造代码实现(示例):

int main()
{
	vector<int> v = { 1,5,7,6,3,4,5 };
	set<int> s1; // 构造空的set
	
	// 用[first, last)区间中的元素构造set
	set<int> s2(v.begin(),v.end()); 
	
	set<int> s3(s2); // set的拷贝构造
	
	return 0;
}

🌙set的迭代器

set的迭代器有点多,其中包括正向迭代器,反向迭代器;const迭代器与非const迭代器

函数声明功能介绍
iterator begin()返回set中起始位置元素的迭代器
iterator end()返回set中最后一个元素后面的迭代器
const_iterator cbegin() const返回set中起始位置元素的const迭代器
const_iterator cend()const 返回set中最后一个元素后面的const迭代器
reverse_iterator rbegin()返回set第一个元素的反向迭代器,即end
reverse_iterator rend()返回set最后一个元素下一个位置的反向迭代器,即rbegin
const_reverse_iterator crbegin() const返回set第一个元素的反向const迭代器,即cend
const_reverse_iterator crend() const返回set最后一个元素下一个位置的反向const迭代器,即crbegin

因而有迭代器的存在,set可以跟方便的遍历整个结构

迭代器实现(示例):

int main()
{
	vector<int> v = { 1,5,7,6,3,4,5 };
	set<int> s1;
	set<int> s2(v.begin(),v.end());
	set<int> s3(s2);
	// 输出s2的遍历结果
	auto it = s2.begin();
	while (it != s2.end())
	{
		cout << *it << " "; // 1 3 4 5 6 7
		it++;
	}
	return 0;
}

⭐set的其他函数操作

函数声明功能介绍
pair<iterator,bool> insert (const value_type& x )在set中插入元素x,实际插入的是<x, x>构成的键值对,如果插入成功,返回<该元素在set中的位置,true>,如果插入失败,说明x在set中已经存在,返回<x在set中的位置,false>
void erase ( iterator position )删除set中position位置上的元素
size_type erase ( const key_type& x )删除set中值为x的元素,返回删除的元素的个数
void erase ( iterator first,iterator last )删除set中[first, last)区间中的元素
void swap (set<Key,Compare,Allocator>&st );交换set中的元素
void clear ( )将set中的元素清空
iterator find ( const key_type& x ) const返回set中值为x的元素的位置
size_type count ( const key_type& x )const 返回set中值为x的元素的个数

在set的这些函数中,用的最多的就是insert,find,erase
在这里插入图片描述

首先insert一般是直接插入元素,或者是一段迭代器区间,在直接插入一个元素时,它的返回值是pair

  • 当插入成功时,first返回新位置的迭代器,然后second返回true;
  • 当set中已经存在该元素时,插入失败,first返回已有元素位置的迭代器,然后second返回false

在这里插入图片描述

  • find不用多说,在set中是找到则返回该位置迭代器
  • multiset中是返回第一个该元素位置的迭代器

在这里插入图片描述

  • erase在set中主要的作用就是删除该迭代器位置的元素,或者删除迭代器区间

  • 第二种用法是针对multiset的,multiset可以有重复元素,因此可以返回删除元素的个数


在这里插入图片描述
在这里插入图片描述

这里介绍两个没有见过的函数upper_bound,lower_bound

  • lower_bound:返回>=该值元素位置的迭代器
  • upper_bound:返回>该值元素位置的迭代器

这两个函数通常可以和erase结合使用删除一段迭代器区间


📚5. map 与 multimap

🎩map的概念

概念: map 是 C++ 标准库中的一个关联容器,它存储的元素都是键值对(key-value pairs),并且键(key)是唯一的。在map中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型value_type绑定在一起,为其取别名称为pair

typedef pair<const key, T> value_type;
  • map支持下标访问符,即在[]中放入key,就可以找到与key对应的value
  • map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))

🎈multimap的概念

概念: multimap 是 C++ 标准库 中的一个关联容器,它允许存储具有相同键的多个值。与 map 不同,map 中的键是唯一的,而 multimap 中的键可以重复

multimap中的接口可以参考map,功能都是类似的。

注意:

  • multimap中的key是可以重复的
  • multimap中的元素默认将key按照小于来比较
  • multimap中没有重载operator[]操作

🧩map的使用

🌈map的模板参数说明

在这里插入图片描述

  • key: 键值对中key的类型
  • T: 键值对中value的类型
  • Compare: 比较器的类型,默认按小于比较

🌞map的构造

函数声明功能介绍
map()构造一个空的map
int main()
{
	map<string,string>(); // 构造一个空的map
	return 0;
}

🌙map的迭代器

函数声明功能介绍
begin()和end()begin:首元素的位置,end最后一个元素的下一个位置
cbegin()和cend()与begin和end意义相同,但cbegin和cend所指向的元素不能修改
rbegin()和rend()反向迭代器,rbegin在end位置,rend在begin位置,其++和–操作与begin和end操作移动相反
crbegin()和crend()与rbegin和rend位置相同,操作相同,但crbegin和crend所指向的元素不能修改

⭐map的其他函数操作

函数声明功能简介
pair<iterator,bool> insert (const value_type& x )在map中插入键值对x,注意x是一个键值对,返回值也是键值对:iterator代表新插入元素的位置,bool代表释放插入成功
size_type erase ( constkey_type& x )删除键值为x的元素
void erase ( iterator first,iterator last )删除[first, last)区间中的元素
iterator find ( const key_type& x)在map中插入key为x的元素,找到返回该元素的位置的迭代器,否则返回end
const_iterator find ( const key_type& x ) const在map中插入key为x的元素,找到返回该元素的位置的const迭代器,否则返回cend
mapped_type& operator[ ] (constkey_type& k)返回去key对应的value

insert
在这里插入图片描述
insert插入中,所需要的元素类型是value_type - > pair

map的成员类型
在这里插入图片描述
在这里插入图片描述
pair可以支持带参构造,无参构造和拷贝构造

map插入代码演示:

int main()
{
	map<string,string> d;
	d.insert(pair<string, string>("insert", "插入"));
	d.insert(pair<const char*, const char*>("find", "查找"));
	return 0;
}

而一般我们并不会这没写,因为有make_pair的存在,我们往往使用make_pair

在这里插入图片描述
在这里插入图片描述
make_pair是一个函数模板,他可以自己推演类型

int main()
{
	map<string,string> d;
	d.insert(make_pair("erase", "删除"));
	return 0;
}

operator[ ]
在这里插入图片描述
在这里插入图片描述

insert:插入成功 pair<新插入key所在节点的iterator, true>插入失败 pair<已经存在的key所在节点的iterator,false>

在使用operator[ ]时,它会自动插入一个元素,在插入成功时,返回该位置的second(默认为0),在插入失败时,它就会返回已有位置的second


📖6. 总结拓展

💧在实际中的应用

这里推荐两个题目让大家巩固set与map
前K个高频单词
两个数组的交集


🔥总结

随着我们深入探讨STL(Standard Template Library)中的map和set,我们不难发现,这两个容器类型在C++编程中扮演着举足轻重的角色。它们不仅提供了高效的数据存储和检索机制,还通过其独特的性质解决了许多实际问题

在学习的过程中,我们领略了map如何以键值对的形式存储数据,并通过键来快速检索值。而set则以其独特的元素唯一性特点,为我们提供了一种确保集合中元素不重复的方法,然而学习之路永无止境。对于mapset的理解和应用,仅仅停留在基本的使用层面是远远不够的。我们需要进一步探索它们的高级用法

学习STL中的容器并不仅仅是为了掌握它们的使用方法。更重要的是,我们要学会如何根据问题的需求选择合适的容器类型,以及如何优化我们的代码以提高程序的性能和可维护性。在这个过程中,我们将会逐渐领悟到编程的精髓和乐趣,让我们一起在学习的道路上不断前行!

在这里插入图片描述

希望本文能够为你提供有益的参考和启示,让我们一起在编程的道路上不断前行!
谢谢大家支持本篇到这里就结束了,祝大家天天开心!

在这里插入图片描述

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

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

相关文章

绿色领航·数链未来“2024中国消费电子博览会”招商工作全面启动

中国国际消费电子博览会&#xff08;简称CICE电博会&#xff09;自2001年创办以来&#xff0c;已逐渐发展成为全球极具影响力的行业盛会。它不仅是国内外消费电子产业的重要交流平台&#xff0c;更是展示我国消费电子产业发展成果的重要窗口。2024年&#xff0c;这一盛会再次在…

windows下前端开发环境安装

文章目录 windows下前端开发环境安装1. Cmder 终端使用1.1 cmder进入指定目录 2. nodejs环境安装3. vscode编辑器下载3.1 vscode插件离线安装 windows下前端开发环境安装 1. Cmder 终端使用 使用Cmder替换cmd&#xff0c;让开发更高效 https://cmder.net/ 打开网址后&#…

系统架构设计师 - 数据库系统(1)

数据库系统 数据库系统数据库模式 ★分布式数据库 ★★★数据库设计阶段 ★★ER模型 ★关系模型 ★ ★结构约束条件完整性约束 关系代数 ★ ★ ★ ★概述自然连接 大家好呀&#xff01;我是小笙&#xff0c;本章我主要分享系统架构设计师 - 数据库系统(1)知识&#xff0c;希望内…

掌握心理学知识成为产品经理一门必修课?

文章目录 心理学与产品设计的关联关系产品经理需要学习哪些心理学知识产品心理学的学习对象包含哪些 谈及心理学&#xff0c;往往认为它是一门研究人类心理现象及其影响下的精神功能和行为活动的科学&#xff0c;很多情况下&#xff0c;我们的直观印象是把心理学与医学领域进行…

Hadoop三大组件原理详解:hdfs-yarn-MapReduce(第9天)

系列文章目录 一、HDFS读写原理【重点】 二、YARN提交mr流程【重点】 三、MapReduce计算流程【重点】 文章目录 系列文章目录前言一、HDFS读写原理[面试]1、HDFS数据写入解析2、HDFS数据读取解析 二、YARN提交mr流程[面试]1. YARN提交mr过程解析 三、MapReduce计算流程[面试]1…

RK3568技术笔记十四 Ubuntu创建共享文件夹

单击“虚拟机”&#xff0c;单击“设置”&#xff0c;如图所示&#xff1a; 单击“选项”&#xff0c;选择“总是启用&#xff08;E&#xff09;”&#xff0c;单击“添加”&#xff0c;如图所示&#xff1a; 单击“下一步”&#xff0c;如图所示&#xff1a; 单击“浏览”添加…

建筑幕墙设计乙级资质申请要点梳理

建筑幕墙设计乙级资质申请要点梳理如下&#xff1a; 一、申请条件 资历和信誉&#xff1a; 企业需具有独立企业法人资格&#xff0c;能够独立承担法律责任。社会信誉良好&#xff0c;无不良记录。注册资本不少于100万元人民币。技术条件&#xff1a; 专业配备齐全、合理&#…

苹果电脑如何清理磁盘空间 苹果电脑如何清理系统数据

你是否遇到过电脑磁盘空间不足的情况呢&#xff1f;Mac电脑有着流畅的操作系统&#xff0c;但是随着日常使用&#xff0c;可能电脑里的垃圾文件越来越多&#xff0c;导致磁盘空间不足&#xff0c;随之会出现电脑卡顿、软件闪退等情况。及时清理磁盘空间可以有效避免电脑这些问题…

java连接kerberos用户认证

文章目录 一、背景二、代码2.1目录2.2配置文件application.properties2.3pom依赖2.4代码AuthProviderConfig配置类CustomConfigurationByKeytab配置类CustomConfigurationByPassword配置类TestControllerMyCallbackHandlerDummyUserDetailsService实现类LdapTest2Application启…

AI播客下载:Possible(OpenAI投资人Reid Hoffman主持)

这是由 LinkedIn 创办人&#xff0c;同时也是 OpenAI 早期投资者 Reid Hoffman。节目上会邀请各领域的专家 (教育、医疗、司法)&#xff0c;探讨 AI 对世界的影响。这节目特别有趣的地方&#xff0c;是在 GPT-4 协助下制作的&#xff0c;开创了人机协作内容 。 如果未来一切都能…

Windows10任务栏卡顿解决方案

一、重新启动任务资源管理器 右键底部任务栏选择“任务管理器”&#xff1b;按快捷键“CtrlShiftEsc”&#xff1b;搜索框搜索“任务管理器”并单击“打开”&#xff1b;“WinX”打开开始菜单附属菜单&#xff0c;在列表中选择“任务管理器” &#xff1b;按下“ctrlaltdelete”…

Linux管道与重定向

管道 是进程通信的方法之一&#xff0c;在Linux中用命令1|命令2的形式表示&#xff0c;将前一个命令的结果作为后续命令的参数进行输入&#xff0c;也有tee管道&#xff0c;可以进行多次筛选&#xff0c;即多次使用|过滤命令。 重定向 文件描述符FD Linux中输入输出分为三种…

HTTP 抓包工具——Fiddler项目实战

网络爬虫实质上是模拟浏览器向 Web 服务器发送请求。对于一些简单的网络请求&#xff0c;我们 可以通过查看 URL 地址来构造请求&#xff0c;但对于一些稍复杂的网络请求&#xff0c;仍然通过观察 URL 地 址将无法构造正确。因此我们需要对这些复杂的网络请求进行捕获分…

高考填报志愿,性格决定命运

所谓性格决定命运&#xff0c;也即是强调了性格在左右我们的人生&#xff0c;性格会和个人的未来成就相挂钩&#xff0c;当一个人向来小心谨慎时&#xff0c;适合一些与数字打交道的工作&#xff0c;也可以从事一些比较细致点的工作&#xff0c;如果一个人向来大大咧咧&#xf…

【Linux命令入门】shell命令解析与PATH环境变量

文章目录 前言1.Linux shell 简介2. Linux命令提示符Linux命令的组成环境变量设置环境变量永久设置临时设置总结前言 Linux命令行(shell)是与操作系统交互的重要工具。通过学习和掌握基本的shell命令,用户可以高效地管理文件、执行程序和处理系统任务。PATH环境变量在Linux…

SpringBoot【3】集成 Swagger

SpringBoot 集成 Swagger 前言pom.xml 配置文件application.yml 配置文件config 包Swagger2Config entity 包UserEntity service 包impl 包SwaggerServiceImpl SwaggerService controller 包SwaggerController SwaggerApplication验证 前言 创建项目步骤、及版本选择等&#x…

从0开始C++(五):友元函数运算符重载

友元函数 介绍 C中的友元函数是一种特殊的函数&#xff0c;它可以访问和操作类的私有成员和保护成员。友元函数可以在类的内部或外部声明和定义&#xff0c;但在其声明和定义中需要使用关键字 friend 来标识。友元函数可以是全局函数&#xff0c;也可以是其他类的成员函数。 …

智慧农业解决方案:华测农机导航技术助力无人农场高效作业

在金黄的麦田、翠绿的稻田中&#xff0c;农机导航正成为无人农场的新星。如今&#xff0c;无人收割、无人播种、无人插秧等作业模式已不再是遥不可及的梦想&#xff0c;而是智慧农业快速发展中的现实写照。搭载华测导航技术的农机&#xff0c;正在田间地头忙碌。它们如同舞者般…

71-TCP协议工作原理及实战

一 服务器端 #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <QTcpServer> // 专门用于建立TCP连接并传输数据信息 #include <QtNetwork> // 此模块提供开发TCP/IP客户端和服务器的类QT_BEGIN_NAMESPACE namespace Ui { class M…

亲测5个电脑浏览器高效技巧,保证让你搜索效率倍增!

虽然我们每个人的电脑基本每天都会用到浏览器&#xff0c;但你会发现有的人用起浏览器就是噼里啪啦的&#xff0c;找他要个什么网站他都能快速找到&#xff0c;而有的人&#xff0c;经常打开的是广告搜索的网页&#xff0c;找不到搜索的答案非常慢。小编今天就来跟你分享一下我…