【C++】STL——set/multiset 和 map/multimap的使用

news2024/9/22 17:24:50

文章目录

  • 1. 关联式容器
  • 2. 树形结构的关联式容器
  • 3. set
    • 3.1 认识set
    • 3.1 set的使用
  • 4. multiset
  • 5. map
    • 5.1 认识map
    • 5.2 pair
    • 5.3 map的使用
      • 对map中[]的理解
  • 6. multimap

1. 关联式容器

在初阶阶段,我们已经接触过STL中的部分容器

在这里插入图片描述
比如:vector、list、deque、forward_list(C++11)等,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身。

而今天我们要学习的几个容器称为关联式容器,那什么是关联式容器?它与序列式容器有什么区别?

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

2. 树形结构的关联式容器

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

树型结构的关联式容器主要有四种:

map、set、multimap、multiset。
这四种容器的共同点是:使用平衡二叉搜索树(即红黑树)作为其底层结构,容器中的元素是一个有序的序列。
关于平衡二叉树我们后面也会讲到,其实我们在前面几篇文章讲解搜索二叉树的时候也提到过,普通的搜索二叉树如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下。
那平衡二叉树顾名思义就是在普通搜索二叉树的基础上让它变的平衡(需要对树中的结点进行调整)。
这个我们后面讲到再细说。

下面一依次介绍每一个容器。

3. set

3.1 认识set

首先我们来看一下set
在这里插入图片描述

还是一个类模板,有三个模板参数,但其实平时我们使用的时候一般只需要管第一个模板参数就行了。
因为后两个都是缺省值的,当然如果你想改变它底层搜索树的排序方式你可以自己传第二个比较方式的仿函数(默认是升序)。

关于set的仔细介绍大家可以去看文档
在这里插入图片描述
不过是英文的,大家可以借助翻译工具查看
在这里插入图片描述

3.1 set的使用

由于我们之前已经学了好几个STL里面的容器,所以这里对于这些容器的使用,其实对我们应该是比较轻松的。所以我这里就不会像之前那样特别仔细去一个个介绍它的接口了,很多东西相信到现在这个阶段大家看着文档都能搞懂
在这里插入图片描述
它提供的接口大家可以先看一下,当然其中一些都不常用。

那我们上面说到:

这几个关联式容器它们的底层结构其实就是我们之前学的二叉搜索树,只不过是平衡搜索树罢了。
那set其实就对应我们前面学的搜索二叉树的应用里面的K模型,下面要学的map就对应KV模型。

那我们接下来就来熟悉一下它的使用:

看一下它的构造函数

在这里插入图片描述
那我们来构造一个空的set,然后插入一些值
首先使用set要包含对于的头文件#include <set>
在这里插入图片描述
我们使用insert插入几个元素(这里我们看他的接口其实就没有push啥的了,一般线性的序列式容器才会有push)。

那然后我想打印出来看看,那我们就可以使用迭代器去遍历它

在这里插入图片描述
但是我们看到这里打印出来是1,2,3,4。
但是我们插入了好几个值啊,并且是无序的,那这里怎么回事呢?
🆗,上面说了它的底层是平衡二叉树,那我们学过二叉搜索树其实就明白怎么回事了:
搜索二叉树一般是不能有重复值的,所以如果多次插入相同的值,后面的就会插入失败(或者可以理解成它会自动进行去重);另外我们知道二叉搜索树也叫做二叉排序树,中序遍历就可以得到一个升序序列,所以这里默认遍历打印出来就是有序了。
所以可以认为set可以实现排序+去重
那支持迭代器的话,我们就可以用范围for。
在这里插入图片描述

那大家思考一下我们可以修改它里面的值吗?

在这里插入图片描述
当然是不行的,因为我们说了它的底层是搜索树,那搜索树如果我们可以任意修改里面的值的话,修改之后还能保证它还是一棵搜索树吗?
就不一定了,因为搜索树是需要满足对于的大小规则的。
所以不能修改。

如果我们想判断一个元素在不在set对象里面

可以用find接口
在这里插入图片描述
在这里插入图片描述
但其实还可以用另一个接口——count
在这里插入图片描述
count是统计元素的个数,但是我们的set里面不允许重复值,所以结果只有1和0,存在就是1,不存在就是0
在这里插入图片描述

那剩下的其它的接口,我们这里就不介绍了,有了前面的基础,相信大家一看就会,还有的就是不怎么用的,或者现阶段我们不是很能看懂的。

4. multiset

那在<set>这个头文件里面呢,出来set,还有一个multiset

在这里插入图片描述
multiset叫做多重集合,multi有多种的意思嘛。
在这里插入图片描述
还是这些接口。

那它跟set有什么区别呢?

🆗,它跟set最大的区别就是允许里面存的key值冗余。
我们可以来看一下
在这里插入图片描述
可以认为它有排序,但没进行去重
那允许键值冗余的话它的插入怎么做呢?
那就接着插就行了,即使插入的是已经存在的值,那搜索树的话我们说大的值要插入到右子树,小的插入到左子树,那现在相等的话其实插入到哪边都可以,可以左边也可以右边,反正平衡二叉树嘛,插入之后会对结点进行调整使得两边平衡(我们后面会讲平衡二叉树)。

然后想给大家说一下find:

现在允许键值冗余了,那就有一个问题:
如果我们find某个值的话,跟他有多个相同的值,那find的时候查找的是哪一个?
🆗,规定呢它find的是中序遍历遇到的第一个。
它遍历的时候底层走的是中序遍历嘛,所以打印出来才是有序的。
我们可以验证一下的:
我们先
现在有4个1,我们find(1),然后从返回的迭代器位置开始,如果能把4个1都打印出来,就证明是中序的第一个1
在这里插入图片描述
当然我们可以用count统计每个键值的个数:
在这里插入图片描述

不过在实际应用中用multiset一般比较少。

5. map

5.1 认识map

map呢其实就对应搜索二叉树的KV模型,它里面存的是<key, value>结构的键值对。即用来表示具有一 一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息。
在这里插入图片描述
在这里插入图片描述
map的接口呢也跟set几乎差不多,有需要注意的我们后面会说。

5.2 pair

那在学习map的使用之前,我们来学一个STL里面的类/结构体模板——pair
在这里插入图片描述

我们来看一下SGI-STL中关于pair的定义:

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

pair的应用:

pair是将2个数据组合成一个数据,当需要这样的需求时就可以使用pair。
(1)STL中的map就是将key和value放在一起来保存(一般first对于key,second对于value)。
(2)另一个应用是,当一个函数需要返回2个数据的时候,可以选择pair

5.3 map的使用

那我们看到map的insert:

在这里插入图片描述
它的第一个版本其实就是接收一个pair类型的对象。
在这里插入图片描述
key是const修饰的,不能修改(即键必须是唯一的),value可以。

那我们来写写代码吧,可以用map写一个我们之前实现的那个英汉互译的词典

map包含在头文件<map>
在这里插入图片描述
当然插入还可以用这个
在这里插入图片描述
那这个make_pair是啥呢?
他其实是库里面提供的一个函数模板
在这里插入图片描述
它可以帮助我们创建一个pair的对象,用它的好处是我们不需要自己去指定类型,因为模板可以自动推导类型。
然后我们来遍历打印一下:
在这里插入图片描述
当然我们也可以这样写:
在这里插入图片描述
那大家看这样可以吗?
在这里插入图片描述
最后一个可以插入成功吗?
在这里插入图片描述
不行,因为键必须是唯一的,不能重复,值可以重复。
一个键只能对应一个值,一个值可以对应多个键
在这里插入图片描述
也可以直接通过find键去查找值
在这里插入图片描述

那我们也用map再写一下统计次数的程序:

跟之前的思路一样,我就直接上代码了
在这里插入图片描述

对map中[]的理解

然后呢,我们发现,map呢还提供了这样一个接口

在这里插入图片描述
它的作用是啥呢?
在这里插入图片描述
首先它接收的参数是键key,如果输入的键与容器中元素的键匹配,就返回该键对应的值的引用。
所以我们刚才的统计次数还可以这样写
在这里插入图片描述
for循环内一行代码,就搞定了

那我们接下来就来研究一下这句代码:

在这里插入图片描述
其实文档上面也解释了,调用这个重载的[]就等效于执行这句代码
(*((this->insert(make_pair(k,mapped_type())).first)).second
所以这个函数大概是这样一个样子:
在这里插入图片描述
我们看到这里面其实去调了一下insert,那我们来仔细研究一下insert的返回值
在这里插入图片描述
我再来解释一下:
首先要知道插入的话呢还是有成功和失败两种情况,因为键值不允许冗余;它返回的是一个pair,第一个模板参数为迭代器,第二个为bool。
当插入成功的时候,pair的first为指向新插入元素的迭代器,second为true,当插入失败的时候(其实就是插入的键已经存在了),那它的first为容器中已存在的那个相同的等效键元素的迭代器,second为false。
所以后面这个bool其实是标识插入成功还是失败。
那我们再来看这个函数
在这里插入图片描述
我们来拆解一下它,要不然不好看
在这里插入图片描述
然后我们再来看里面这个insert
在这里插入图片描述
我们看到这里面insert也是使用make_pair这个函数创建一个pair对象,第一个参数就是我们[]里面放的那个键key,第二个参数传的是啥呢?
我们看到它是调了值value的类型的默认构造(之前我们说过有了模板之后内置类型就也需要有构造函数了),那我们的value是int,默认构造的值是0,所以我们第一次插入刚好它的次数就是0了。然后返回这个次数对应的value的引用,外面对它++,就正好是1。
然后后续插入相同键的话,就插入失败,不会将次数变成0,但是依然返回次数(对应pair中的second)的引用,我们从1继续往上++就行了,
当然它这上面给的有些类型是进行了typedef的,我们不太好看,不过它提供了一个表,大家可以查阅
在这里插入图片描述
所以我们可以将它简化一下,方便看
在这里插入图片描述

所以我们也可以这样玩:

在这里插入图片描述
插入,查找、修改啥的操作这样写
在这里插入图片描述

总结

1. map中的的元素是键值对
2. map中的key是唯一的,并且不能修改
3. 默认按照小于的方式对key进行比较
4. map中的元素如果用迭代器去遍历,可以得到一个有序的序列
5. map的底层为平衡搜索树(红黑树),查找效率比较高 O ( l o g 2 N ) O(log_2 N) O(log2N)
6. 支持[]操作符,operator[]中实际进行插入查找

6. multimap

那和set一样:

除了map还有multimap
在这里插入图片描述

我们看一下

在这里插入图片描述
同样的,跟map相比,multimap允许键key冗余
在这里插入图片描述
所以它的接口里面就没有[]

简单演示一下:

在这里插入图片描述
当然key和value都相同也是可以的。

然后其它的就不多说了,有需要大家可以自己查阅文档。
在这里插入图片描述

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

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

相关文章

VoxWeekly|The Sandbox 生态周报|20230807

欢迎来到由 The Sandbox 发布的《VoxWeekly》。我们会在每周发布&#xff0c;对上一周 The Sandbox 生态系统所发生的事情进行总结。 如果你喜欢我们内容&#xff0c;欢迎与朋友和家人分享。请订阅我们的 Medium 、关注我们的 Twitter&#xff0c;并加入 Discord 社区&#xf…

c++--AVL树简单实现

1.什么是AVL树 AVL树就是在搜索二叉树的基础上通过控制左右子树的高度差实现的&#xff0c;在搜索二叉树的基础上&#xff0c;通过旋转来控制&#xff0c;是左右子树高度差的绝对值严格控制为不超过1&#xff08;通过旋转来控制树的高度&#xff09;。由于搜索二叉树的效率最差…

一起学SF框架系列7.1-spring-AOP-基础知识

AOP(Aspect-oriented Programming-面向切面编程&#xff09;是一种编程模式&#xff0c;是对OOP(Object-oriented Programming-面向对象编程&#xff09;一种有益补充。在OOP中&#xff0c;万事万物都是独立的对象&#xff0c;对象相互耦合关系是基于业务进行的&#xff1b;但在…

【逗老师的PMP学习笔记】8、项目质量管理

目录 一、规划质量管理1、质量管理的发展历史2、戴明环&#xff0c;PDCA理论3、【关键输入】事业环境因素4、【关键输入】成本效益分析5、【关键工具】质量成本6、【关键输出】质量管理计划7、插一嘴&#xff0c;项目的三个标准8、【关键工具】质量测量指标 二、管理质量1、【关…

[OnWork.Tools]系列 06-屏幕水印

简介 屏幕水印功能主要是在开会分享屏幕的时候在屏幕上增加水印 水印使用 水印启用和颜色设置 水印文字和大小设置 水印间距,透明度,角度调整

保护电脑健康,这些维护技巧你Get了吗?

文章目录 1.界面环境1.1合理布置终端桌面1.2清理垃圾信息1.3关注运行环境和系统信息 2.程序管理2.1安装软件时需谨慎2.2及时更新软件和操作系统2.3合理管理插件和工具栏 3.网络防护3.1保护个人隐私3.2防范网络攻击3.3备份重要数据 4.电源管理4.1合理关机和电源设置4.2定期清理灰…

ESP32开发阶段启用 Secure Boot 与 Flash encryption

Secure Boot 与 Flash encryption详情 请参考&#xff1a;https://blog.csdn.net/espressif/article/details/79362094 1、开发环境 AT版本&#xff1a;2.4.0.0 发布IDF 与 python&#xff1a; idf4.3_py3.10_env系统&#xff1a;虚拟机 ubuntu 20 2、使能 secure boot 和 …

手搓 自然语言模型 LLM 拆分em结构设计 网络参数对比

数据 数据集 新的em编码参数表 voc_sizehidden_sizetotaltotal Bmax_lensecondsdays65536512374865920.03749B10242560.2655361024828375040.08284B20485120.5655362048<

yo!这里是STL::list类简单模拟实现

目录 前言 重要接口实现 框架 默认成员函数 迭代器&#xff08;重点&#xff09; 1.引言 2.list迭代器类实现 3.list类中调用实现 增删查改 后记 前言 我们知道&#xff0c;stl中的vector对应数据结构中的顺序表&#xff0c;string类对应字符串&#xff0c;而今天要…

Spring Data学习笔记Day01-SpringData入门

Spring Data基本介绍 目录 Spring Data Redis 官方API参考手册&#xff01;★ Spring Data的价值★ Spring Data及其子项目★ 强大的Spring Data★ Repository接口★ 具体Repository接口★ Spring Data JPA开发★ Spring Boot如何选择DataSource★ 数据源相关配置★ 配置第三方…

spring源码高级-图灵周瑜

实现factorybean可以产生代理对象

文件数字水印,附一种纯文本隐写术数字水印方法

数字水印&#xff08;Digital Watermark&#xff09;是一种在数字媒体文件中嵌入隐藏信息的技术。这些数字媒体可以是图片、音频、视频或文本等。数字水印不会对原始文件造成明显的视觉或听觉变化&#xff0c;但可以在一定程度上保护知识产权&#xff0c;追踪数据来源&#xff…

4个不是镜像但生成质量不输ChatGPT的其他AI聊天机器人

最近又发现其他几个类似ChatGPT的好用且质量还不错的AI聊天机器人&#xff0c;特意分享给大家。 Bing AI Bing AI工作原理与OpenAI的ChatGPT非常相似。Bing AI聊天机器人是利用ChatGPT的大语言模型&#xff0c;能够生成不同形式的内容&#xff0c;例如博客、文章、描述、诗歌等…

尚硅谷大数据项目《在线教育之采集系统》笔记004

视频地址&#xff1a;尚硅谷大数据项目《在线教育之采集系统》_哔哩哔哩_bilibili 目录 P047 P048 P049 P050 P051 P052 P053 P054 P055 P056 P047 /opt/module/datax/job/base_province.json [atguigunode001 ~]$ hadoop fs -mkdir /base_province/2022-02-22 [atgu…

动手学深度学习Pytorch 4.4练习

1.这个多项式回归问题可以准确地解出吗&#xff1f;提⽰&#xff1a;使⽤线性代数。 可以,把多项式问题&#xff0c;用matlab的str2sym表示出来&#xff0c;再用solve求解。 2.考虑多项式的模型选择。 1. 绘制训练损失与模型复杂度&#xff08;多项式的阶数&#xff09;的关系…

以太网收发及TSN概述

一、概述 TSN&#xff08;Time-Sensitive Networking&#xff09;时间敏感网络&#xff0c;即在非确定性的以太网中实现确定性的最小时间延时的协议族&#xff0c;是IEEE 802.1工作组中的TSN工作组开发的一套协议标准&#xff0c;定义了以太网数据传输的时间敏感机制&#xff…

探析青少年口才训练在个人发展中的重要性与影响

论文题目&#xff1a;探析青少年口才训练在个人发展中的重要性与影响 摘要&#xff1a; 本论文旨在探讨青少年口才训练对个人发展的重要性和影响。通过对相关文献的综述和实证研究的分析&#xff0c;论文将阐述口才训练对青少年自信心、表达能力和思维能力的提升&#xff0c;以…

常见分布式ID解决方案总结:数据库、算法、开源组件

常见分布式ID解决方案总结 分布式ID分布式ID方案之数据库数据库主键自增数据库号段模式Redis自增MongoDB 分布式ID方案之算法UUIDSnowflake(雪花算法) 雪花算法的使用IdWorker工具类配置分布式ID生成器 分布式ID方案之开源组件uid- generator(百度)Tinyid&#xff08;滴滴&…

Leetcode.1559 二维网格图中探测环

题目链接 Leetcode.1559 二维网格图中探测环 rating : 1838 题目描述 给你一个二维字符网格数组 g r i d grid grid &#xff0c;大小为 m x n &#xff0c;你需要检查 g r i d grid grid 中是否存在 相同值 形成的环。 一个环是一条开始和结束于同一个格子的长度 大于等于…

Java基础(四)

循环结构 1. while循环 循环变量初始化 while (循环条件){循环体; }循环条件是一个布尔类型的表达式&#xff0c;他的值为 true 时执行循环体&#xff0c;如果为 false 时终止循环体。while 循环是先判断条件是否成立&#xff0c;再决定是否执行循环体。如果第一次循环时&…