C++笔记-set和map的使用(包含multiset和multimap的讲解)

news2025/5/11 9:43:51

1.序列式容器和关联式容器

前面我们已经接触过STL中的部分容器如:string、vector、list、deque、array、forward_list等,这些容器统称为序列式容器,因为逻辑结构为线性序列的数据结构,两个位置存储的值之间一般没有紧密的关联关系,比如交换一下,他依旧是序列式容器。顺序容器中的元素是按他们在容器中的存储位置来顺序保存和访问的。
关联式容器也是用来存储数据的,与序列式容器不同的是,关联式容器逻辑结构通常是非线性结构,两个位置有紧密的关联关系,交换一下,他的存储结构就被破坏了。顺序容器中的元素是按关键字来保存和访问的。关联式容器有map/set系列和unordered_map/unordered_set系列。
本章节讲解的map和set底层是红黑树,红黑树是一颗平衡二叉搜索树。set是key搜索场景的结构, map是key/value搜索场景的结构。

1.set系列的使用

1.1set的介绍

set就是我们上篇所实现的二叉搜索树的key搜索场景,它默认就是不存在重复数据的二叉搜索树,尔汗有重复数据的就是后面要讲的mutiset。

从上图可以看出,set的模板参数中含有三个不同的类型,第一个想必大家都知道,就是里面存储数据的类型。

第二个我们之前也讲过,就是仿函数,可以控制数据的输出顺序。

第三个是内存池,这部分知识我们还没有了解,这里就先跳过。

从以上图片可以看出,和我们之前所学的其它容器还是比较相似的,使用起来也非常相似:

这里可以看到set自动就对所传入的数据进行去重,并且按照升序排序的方式,而我们如果想让其输出的方式是从大到小,也可以利用仿函数:

并且我们是不能修改set中的值:

不能修改的原因呢我们上一篇已经讲过,会破坏二叉搜索树的结构,如果能修改那么二叉搜索树就失去了意义。

下面来讲解set中一些接口的使用方法。

1.2find

set中的find接口通过传入的值进行查找,如果找到了就返回相应的迭代器,也就是对应数据的位置,如果没有找到,就返回end()迭代器。

这里我们通过find接口来找5这个数据,结果显示找到了,说明此时返回的迭代器并不是end()。

而如果我们来找1这个数据,结果并没有找到,说明此时find返回的就是end()。

1.3erase

erase和我们之前所学容器的erase有些不一样,从上图对set的介绍可以看出,除了我们常见的void返回值以外,还有个size_type做返回值的。

而在set中这个size_type就是0或者1,删除成功返回1,删除失败就返回0,而这样设计的原因是为了和mutiset相照应。

可以看出此时的返回值时1,说明删除成功,我们通过再次打印出set中的数据也可以看到2已经被删除。

这里我们要删除1,发现删除失败,此时erase的返回值就为0。

1.4count

count接口就是来查找某个数据有几个,而在set中我们知道数据要么没有,要么只有一个,所以在set中count主要用来判断传入的数据在不在。

count的返回值依旧是1或者0,我们可以利用count的这个功能来写一种题型:

比如就像力扣上的这种题,我们就可以利用set来解决会更加的简单:

因为一个数组中蛊蛾可能会有重复的数据,所以利用set的去重特性以及count判断数据在不在,这道题写起来就极为简单。

1.5low_bound和upper_bound

low_bound的作用是对于所传入的数据找出set中大于等于这个数据的第一个值的位置,所以返回值也是迭代器。

upper_bound的作用是对于所传入的数据找出set中大于这个数据的第一个值的位置。

两者的区别就是一个是>=,一个是>。

那么这两个功能有什么用呢?

这两个配合着erase接口就可以实现删除set中的某段内容,就如上面的例子所示,>=30的第一个数就是30,而>70的第一个数就是80,但是为什么没有删除80呢?
因为在c++中的删除范围都是左闭右开,在这里就是[30,80),所以删除的就是30到70这几个数据,当然我们也可以改一下数据再看看到底是不是这样:

可以看出,这里我传的并不是set中的数据,和上面一样>=25的第一个数就是30,>75的第一个数是80,所以结果是一样的。

2.multiset

multiset和set差不多,无非就是一个不去重,一个去重。从上图也可以看出,mutiset和set接口都一模一样,我们下面来看一下mutiset的基本使用:

可以看出multiset并没有去重,并且和set一样都是升序排列。

当然。multiset和set的区别并不是只有这一点,在某些接口中也有细微的差别。

2.1find

find呢,在multiset返回的是某个数据在中序中的第一个位置,何为在中序中的第一个位置呢?

就如上面所查找的4,中序中的第一个4就是最左的那个位置,从上面找到后继续查找4也可以看出找的就是第一个位置,所以才能将后面的4都打印出来。

2.3erase

此时在multiset中erase返回就不只是0或1了,所以上面的set中的erase返回值也是size_type,就是为了和multiset相照应,而是返回这个数据有几个被删掉了。

当然,如果只想删除一个,我们就要指定对应的位置进行删除,比如:

这里我们利用find找到了第一个4所在的位置,并将其传给erase,这样就可以只删除一个4。

2.4count

在multiset中count就真正变为统计每个数有几个,这里可以看出统计了4,2,6的数量。

3.map

3.1map的介绍

map就是我们之前讲的key/value搜索场景,在map的解释中呢我们可以看到有一个pair的模板,这个pair是什么呢?

pair其实是一个结构体,里面保存着key和value,那么可能有人会有疑惑:为什么不和我们上一篇所讲的放在一块呢?

因为我们要对map的迭代器进行解引用啊,如果放在一起,解引用能解出来两个值吗?

显然是不行的,所以就没有放在一块,它多写个结构体就是这样:

就是把之前的key和val更换为pair,就是多加了一步。

而我们使用insert赋值时最简单的方法就是利用隐式类型转换,另外注意我们在打印出key和val时是上述的方式来打印,利用迭代器也是一样:

当然,也可以用下面这种方式:

这也是我们之前讲的->符号重载。

我们是无法直接对迭代器进行解引用,为什么呢?
因为底层的pair并没有重载流插入<<和流提取>>,所以我们是不能直接对迭代器直接接引用进行使用。

3.2[]符号重载

看到这个接口,可能有人会有疑惑:[]符号不是底层是数组才会用[]来进行下标访问吗?

是的,不过map的[]并不是用来进行下标访问的,而是另有用处:

通过看[]符号重载的基本格式我们可以看出,[]符号传入的值是key,而返回的值却是value,而要理解[]符号重载的原理我们先看一个例子:

比如我们要插入上述的几种水果并统计它们的次数,按照正常的逻辑我们应该用上面的代码来写对吧,但是我们再看:

而当我们利用[]来写时,一行代码就搞定了,有人会有疑惑:为什么这么写就和前面是一样的效果呢?

其实原理就和前面的代码是一样的,其实[]符号重载就是利用insert接口来实现的,大家可以设想一下,我来查找这个数据返回的是它的second,如果有的情况下++即可,但是没有的话怎么办?

那肯定得先插入这个数据对吧,所以才要利用insert来实现,那现在我们再看insert接口:

我们来看insert的第一种方式,这里也有一个pair,并且和我们上面讲的pair参数并不一样,确实是这样的,大家不要将两者混为一谈,这是两个不同pair。

而第二张图呢就是对这个pair的解释,意思是:根据你传入的key,第一个参数iterator指向的是新插入的数据的位置或者是已经在map中存在的数据的位置,而第二个参数bool在是插入新的数据时默认是true,而如果要插入的数据已经存在,那么就是false。

也就是说,不管你传入的key是否存在,pair中的第一个参数iterator都会获得一个位置,这也是[]符号重载能实现的关键。

现在我们大概来看看[]符号重载是怎么实现的:

大概就是这么个逻辑,这里要注意insert的第二个参数我们可以传匿名对象,这样就会去调用相应的默认构造函数,比如:int就会默认是0等。

而当我们通过第一段代码得到pair时,我们就可以访问其中的第一个参数iterator得到对应的位置,而第二段代码中的ret.first就是iterator,再通过->来访问结构体中的second,也就是水果的次数。

通过[]符号重载,我们既实现了插入新的数据,又能统计每个水果出现的次数。

基于[]的这个特性,我们还可以这样写:

再插入数据时我们可以不直接调用insert接口,而是利用[]符号重载来实现。

4.multimap

multimap和map也是几乎没什么区别,和上面的set/multiset情况是一样的,multimap可以插入重复的数据。

并且我们可以看到multimap是没有[]符号重载的,没有的原因大家想想都应该清楚,如果支持的话并且其中有重复值,那么我该返回哪个的second呢?

multimap剩下的接口和map是一模一样的,这里我再讲一个接口:equal_range

equal_range这个接口的功能就是返回key值相等的一段区间,从它的返回值也可以看出也是pair,第一个参数就是起始位置的iterator,第二个参数就是最后一个位置的下一个位置的iterator,因为是左闭右开嘛。

这就是equal_range的基本应用场景,而在map中这个方法显然只能返回一个元素。

这个接口包括multimap用的都不多,了解一下即可。

以上就是set和map的使用的内容。

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

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

相关文章

Linux `ifconfig` 指令深度解析与替代方案指南

Linux `ifconfig` 指令深度解析与替代方案指南 一、核心功能与现状1. 基础作用2. 版本适配二、基础语法与常用操作1. 标准语法2. 常用操作速查显示所有接口信息启用/禁用接口配置IPv4地址修改MAC地址(临时)三、高级配置技巧1. 虚拟接口创建2. MTU调整3. 多播配置4. ARP控制四…

Python pandas 向excel追加数据,不覆盖之前的数据

最近突然看了一下pandas向excel追加数据的方法&#xff0c;发现有很多人出了一些馊主意&#xff1b; 比如用concat,append等方法&#xff0c;这种方法的会先将旧数据df_1读取到内存&#xff0c;再把新数据df_2与旧的合并&#xff0c;形成df_new,再覆盖写入&#xff0c;消耗和速…

【金仓数据库征文】政府项目数据库迁移:从MySQL 5.7到KingbaseES的蜕变之路

摘要&#xff1a;本文详细阐述了政府项目中将 MySQL 5.7 数据库迁移至 KingbaseES 的全过程&#xff0c;涵盖迁移前的环境评估、数据梳理和工具准备&#xff0c;迁移实战中的数据源与目标库连接配置、迁移任务详细设定、执行迁移与过程监控&#xff0c;以及迁移后的质量验证、系…

Go语言——goflow工作流使用

一、引入依赖 这个很坑&#xff0c;他不允许连接带密码的redis&#xff0c;只能使用不带密码的redis&#xff0c;要带密码的话得自己改一下源代码&#xff0c;无语 go get github.com/s8sg/goflow二、画出我们的工作流程 三、编写代码 package mainimport ("encoding/j…

yarn npm pnpm

1 下载方式 npm 之前串行下载 现在并行下载 yarn 并行下载 加入缓存复用 pnpm 硬连接 避免重复下载&#xff0c;先检查本地是否存在&#xff0c;存在的话直接连接过去

Block Styler——字符串控件

字符串控件的应用 参考官方帮助案例&#xff1a;&#xff08;这个方式感觉更好&#xff0c;第二种方式也可以&#xff09;E:\NX1980\UGOPEN\SampleNXOpenApplications\C\BlockStyler\ColoredBlock 普通格式&#xff1a; 读取&#xff1a; //方法一 string0->GetProperti…

LangGraph(三)——添加记忆

目录 1. 创建MemorySaver检查指针2. 构建并编译Graph3. 与聊天机器人互动4. 问一个后续问题5. 检查State参考 1. 创建MemorySaver检查指针 创建MemorySaver检查指针&#xff1a; from langgraph.checkpoint.memory import MemorySavermemory MemorySaver()这是位于内存中的检…

【无标题】I/O复用(epoll)三者区别▲

一、SOCKET-IO复用技术 定义&#xff1a;SOCKET - IO复用技术是一种高效处理多个套接字&#xff08;socket&#xff09;的手段&#xff0c;能让单个线程同时监听多个文件描述符&#xff08;如套接字&#xff09;上的I/O事件&#xff08;像可读、可写、异常&#xff09;&#x…

ClassLoader类加载机制的核心引擎

ClassLoader类加载机制的核心引擎 文章目录 ClassLoader类加载机制的核心引擎1. ClassLoader基础1.1 什么是ClassLoader&#xff1f;1.2 ClassLoader的层次结构1.3 类加载的过程 2. 源码解析与工作原理2.1 ClassLoader的核心方法2.2 双亲委派模型的工作原理2.3 打破双亲委派模型…

tryhackme——Enumerating Active Directory

文章目录 一、凭据注入1.1 RUNAS1.2 SYSVOL1.3 IP和主机名 二、通过Microsoft Management Console枚举AD三、通过命令行net命令枚举四、通过powershell枚举 一、凭据注入 1.1 RUNAS 当获得AD凭证<用户名>:<密码>但无法登录域内机器时&#xff0c;runas.exe可帮助…

【Linux学习笔记】系统文件IO之重定向原理分析

【Linux学习笔记】系统文件IO之重定向原理分析 &#x1f525;个人主页&#xff1a;大白的编程日记 &#x1f525;专栏&#xff1a;Linux学习笔记 文章目录 【Linux学习笔记】系统文件IO之重定向原理分析前言一. 系统文件I/01.1 一种传递标志位的方法1.2 hello.c写文件:1.3 he…

SpringBoot中使用MCP和通义千问来处理和分析数据-连接本地数据库并生成实体类

文章目录 前言一、正文1.1 项目结构1.2 项目环境1.3 完整代码1.3.1 spring-mcp-demo的pom文件1.3.2 generate-code-server的pom文件1.3.3 ChatClientConfig1.3.4 FileTemplateConfig1.3.5 ServiceProviderConfig1.3.6 GenerateCodeController1.3.7 Columns1.3.8 Tables1.3.9 Fi…

实现滑动选择器从离散型的数组中选择

1.使用原生的input 详细代码如下&#xff1a; <template><div class"slider-container"><!-- 滑动条 --><inputtype"range"v-model.number"sliderIndex":min"0":max"customValues.length - 1"step&qu…

基于Credit的流量控制

流量控制(Flow Control)&#xff0c;也叫流控&#xff0c;它是控制组件之间发送和接收信息的过程。在总线中&#xff0c;流控的基本单位称为flit。 在标准同步接口中(比如AXI协议接口)&#xff0c;握手信号如果直接采用寄存器打拍的方式容易导致信号在不同的方向上出现偏离。因…

【金仓数据库征文】金仓数据库KingbaseES: 技术优势与实践指南(包含安装)

目录 前言 引言 一 : 关于KingbaseES,他有那些优势呢? 核心特性 典型应用场景 政务信息化 金融核心系统&#xff1a; 能源通信行业&#xff1a; 企业级信息系统&#xff1a; 二: 下载安装KingbaseES 三:目录一览表: 四:常用SQL语句 创建表&#xff1a; 修改表结构…

金丝猴食品:智能中枢AI-COP构建全链路数智化运营体系

“金丝猴奶糖”&#xff0c;这个曾藏在无数人童年口袋里的甜蜜符号&#xff0c;如今正经历一场数智焕新。当传统糖果遇上数字浪潮&#xff0c;这家承载着几代人味蕾记忆的企业&#xff0c;选择以数智化协同运营平台为“新配方”&#xff0c;将童年味道酿成智慧管理的醇香——让…

java的输入输出模板(ACM模式)

文章目录 1、前置准备2、普通输入输出API①、输入API②、输出API 3、快速输入输出API①、BufferedReader②、BufferedWriter 案例题目描述代码 面试有时候要acm模式&#xff0c;刷惯leetcode可能会手生不会acm模式&#xff0c;该文直接通过几个题来熟悉java的输入输出模板&…

鸿蒙 所有API缩略图鉴

从HarmonyOS NEXT Developer Preview1&#xff08;API 11&#xff09;版本开始&#xff0c;HarmonyOS SDK以 Kit 维度提供丰富、完备的开放能力&#xff0c;涵盖应用框架、应用服务、系统、媒体、AI、图形在内的六大领域&#xff0c;共计30000个API

【Docker系列】使用格式化输出与排序技巧

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

基础语法(二)

Mysql基础语法&#xff08;二&#xff09; Mysql基础语法&#xff08;二&#xff09;主要介绍Mysql中稍微进阶一点的内容&#xff0c;会稍微有一些难度&#xff08;博主个人认为&#xff09;。学习完基础语法&#xff08;一&#xff09;和基础语法&#xff08;二&#xff09;之…