C++笔记-set和map的使用(包含multiset和multimap的讲解)
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的使用的内容。
相关文章:

C++笔记-set和map的使用(包含multiset和multimap的讲解)
1.序列式容器和关联式容器 前面我们已经接触过STL中的部分容器如:string、vector、list、deque、array、forward_list等,这些容器统称为序列式容器,因为逻辑结构为线性序列的数据结构,两个位置存储的值之间一般没有紧密的关联关系࿰…...
宝蓝德中间件部署war包时,配置的绝对路径读取错误。
文章目录 问题场景解决办法宝蓝德是什么??一、基础环境与依赖配置二、自动化部署工具链三、高可用性与集群配置四、安全与合规性措施五、产品线差异化部署六、典型部署流程示例七、运维与优化 原因1. 明确“当前工作目录”与“绝对路径”的关系2. 问题根…...

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

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

【金仓数据库征文】政府项目数据库迁移:从MySQL 5.7到KingbaseES的蜕变之路
摘要:本文详细阐述了政府项目中将 MySQL 5.7 数据库迁移至 KingbaseES 的全过程,涵盖迁移前的环境评估、数据梳理和工具准备,迁移实战中的数据源与目标库连接配置、迁移任务详细设定、执行迁移与过程监控,以及迁移后的质量验证、系…...

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

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

Block Styler——字符串控件
字符串控件的应用 参考官方帮助案例:(这个方式感觉更好,第二种方式也可以)E:\NX1980\UGOPEN\SampleNXOpenApplications\C\BlockStyler\ColoredBlock 普通格式: 读取: //方法一 string0->GetProperti…...

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

【无标题】I/O复用(epoll)三者区别▲
一、SOCKET-IO复用技术 定义:SOCKET - IO复用技术是一种高效处理多个套接字(socket)的手段,能让单个线程同时监听多个文件描述符(如套接字)上的I/O事件(像可读、可写、异常)&#x…...
通俗的理解MFC消息机制
1. 消息是什么? 想象你家的门铃响了(比如有人按门铃、敲门、或者有快递),这些都是“消息”。 在 MFC 中,消息就是系统或用户触发的各种事件,比如鼠标点击(WM_LBUTTONDOWN)、键盘输入…...

ClassLoader类加载机制的核心引擎
ClassLoader类加载机制的核心引擎 文章目录 ClassLoader类加载机制的核心引擎1. ClassLoader基础1.1 什么是ClassLoader?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凭证<用户名>:<密码>但无法登录域内机器时,runas.exe可帮助…...

【Linux学习笔记】系统文件IO之重定向原理分析
【Linux学习笔记】系统文件IO之重定向原理分析 🔥个人主页:大白的编程日记 🔥专栏:Linux学习笔记 文章目录 【Linux学习笔记】系统文件IO之重定向原理分析前言一. 系统文件I/01.1 一种传递标志位的方法1.2 hello.c写文件:1.3 he…...
【新教程】Linux服务器ssh启用两步验证
1 背景 服务器被恶意破解的事件层出不穷,一旦被破解就比较麻烦。不如提前通过简单的措施——增加两步验证,来大大增强服务器的安全性。本教程在Debian 12.5、Ubuntu 24.04等系统上测试通过。 2 详细过程 1、安装 libpam-google-authenticator sudo a…...

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 详细代码如下: <template><div class"slider-container"><!-- 滑动条 --><inputtype"range"v-model.number"sliderIndex":min"0":max"customValues.length - 1"step&qu…...

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

【金仓数据库征文】金仓数据库KingbaseES: 技术优势与实践指南(包含安装)
目录 前言 引言 一 : 关于KingbaseES,他有那些优势呢? 核心特性 典型应用场景 政务信息化 金融核心系统: 能源通信行业: 企业级信息系统: 二: 下载安装KingbaseES 三:目录一览表: 四:常用SQL语句 创建表: 修改表结构…...
LLaVA:开源多模态大语言模型深度解析
一、基本介绍 1.1 项目背景与定位 LLaVA(Large Language and Vision Assistant)是由Haotian Liu等人开发的开源多模态大语言模型,旨在实现GPT-4级别的视觉-语言交互能力。该项目通过视觉指令微调技术,将预训练的视觉编码器与语言模型深度融合,在多个多模态基准测试中达到…...

金丝猴食品:智能中枢AI-COP构建全链路数智化运营体系
“金丝猴奶糖”,这个曾藏在无数人童年口袋里的甜蜜符号,如今正经历一场数智焕新。当传统糖果遇上数字浪潮,这家承载着几代人味蕾记忆的企业,选择以数智化协同运营平台为“新配方”,将童年味道酿成智慧管理的醇香——让…...
泛型设计模式实践
学海无涯,志当存远。燃心砺志,奋进不辍。 愿诸君得此鸡汤,如沐春风,事业有成。 若觉此言甚善,烦请赐赞一枚,共励学途,同铸辉煌! 为解决在设计框架或库时遇到的类型安全问题ÿ…...

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

鸿蒙 所有API缩略图鉴
从HarmonyOS NEXT Developer Preview1(API 11)版本开始,HarmonyOS SDK以 Kit 维度提供丰富、完备的开放能力,涵盖应用框架、应用服务、系统、媒体、AI、图形在内的六大领域,共计30000个API...
【LangChain全景指南】构建下一代AI应用的开发框架
目录 🌟 前言🏗️ 技术背景与价值🚧 当前技术痛点🛠️ 解决方案概述👥 目标读者说明 🔍 一、技术原理剖析📊 核心概念图解💡 核心作用讲解🧩 关键技术模块说明⚖️ 技术选…...
垃圾对象回收
1.如何判断对象可以被回收 对象是否可以被回收通常由垃圾回收器决定。 垃圾回收器使用一种称为"可达性分析"的算法来确定对象是否可被回收。 可达性分析是指如果一个对象无法从任何GCRoots直接或间接访问到,它就被认为是不可达的,可以被垃圾回…...

【Docker系列】使用格式化输出与排序技巧
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
nvme Unable to change power state from D3cold to D0, device inaccessible
有个thinkpad l15 gen4笔记本,使用较少,有一块三星m2和东芝14t硬盘,想安装飞牛nas系统作为家庭照片库,制作飞牛启动盘,发现安装飞牛需要全盘格式化,电脑本身的系统还是需要保留的,故想到再安装一…...

基础语法(二)
Mysql基础语法(二) Mysql基础语法(二)主要介绍Mysql中稍微进阶一点的内容,会稍微有一些难度(博主个人认为)。学习完基础语法(一)和基础语法(二)之…...
AcWing 877:扩展欧几里得算法
【题目来源】 https://www.acwing.com/problem/content/879/ 【题目描述】 给定 n 对正整数 ai,bi,对于每对数,求出一组 xi,yi,使其满足 aixibiyigcd(ai,bi)。 【输入格式】 第一行包含整数 n。接下来 n 行,每行包含两个整数 ai…...