map和set的介绍和使用

文章目录

    • map和set
      • 关联式容器
      • 键值对
      • set
        • 介绍
        • 模板参数
      • map
        • 介绍
        • 模板参数
        • 为什么map支持下标访问
      • multiset
        • 介绍
      • multimap

map和set

关联式容器

我们在之前讲过STL的一些基础容器,例如vector,list,deque,forward_list等

这些其实统一都称为序列式容器,因为其底层都是线性的序列数据结构,而且存储的内容是元素本身

关联式容器也是存储数据的容器,不同的是,里面存储的是<key,value>的键值对,类似于我们之前讲的二叉搜索树的KV模型

键值对

键值对是我们用来表示一一对应关系的结构,包含key和value两个成员变量

key表示关键字,类似于字典中的单词,value表示具体的值,也就是字典中对应的具体释义

在C++中使用pair表示一对值,但并没有具体的对应关系,只是将这一对值进行了封装,可以读取和写入,当然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){}
};

set

介绍

set的文档

set直接翻译成中文是集合,而他与数学意义上的集合也有不同的地方,set是要求有序的,其次set中的元素不能被修改,元素是const的,但是允许插入删除

set的有序是可以自行定义升序或者降序的,默认是按照小于排序(升序),不允许重复值

set容器通过key访问单个元素的速度比unordered_set慢,但是都允许根据顺序对子集直接迭代

set在底层是使用二叉搜索树的红黑树实现的

set的底层实际上也是有pair的,只不过是<value,value>的形式,在插入元素时,只需要插入value即可

set查找的时间复杂度是 log ⁡ 2 n \log_2n log2n

模板参数

屏幕截图 2024-03-13 172738.png

第一行的T是存放元素的类型,实际是存在底层的<value,value>键值对

第二行的Compare是仿函数,用于确定是升序还是降序,默认为升序

第三行是一个空间配置器

这里其他的内容参考set的官方文档即可

map

介绍

map文档

map是关联容器,直接翻译称为映射,是我们之前讲的二叉搜索树的KV模型,他存储的元素是一个有key和value构成的有序对

在map中,key是唯一的,用于标识value

STL中使用typedef来减少长度

typedef pair<const key, T> value_type;

map内部是对key值排序,默认是升序,他对单个元素的访问速度比unordered_map慢,但是map允许根据顺序对元素进行直接迭代

map支持下标访问,可以直接找到与key对应的value,这里的实现让人赞叹

map的底层是由红黑树实现的,我们在之后的内容里也会使用红黑树实现set和map

模板参数

image.png

Key是键值对中的key,T对应的是value,后面分别是仿函数和空间配置器

需要注意的是,这里的map::key_type和map::mapped_type是typedef出的

image.png

这里我们注意到一个细节,在定义pair的时候,first被const了,说明key值是不能被修改的

为什么map支持下标访问

我们看map对方括号的重定义

image.png

image.png

也就是说他内部是这样实现的

mapped_type& operator[] (const key_type& k)
{return *((this->insert(make_pair(k,mapped_type())).first)).second;
}

这里看上去比较复杂,我们剥洋葱一样的来看

第一层是调用了map的insert插入函数,我们来看insert的定义

image.png

这里调用的是单参数的insert,value_type是一个pair对象,我们可以通过make_pair的名称就知道,他是用于构建pair对象的

insert的返回值是也一个pair对象,first是迭代器,bool是用来表示插入是否成功,如果成果,first指向的就是新pair,如果失败first指向的就是已经存在的pair

然后来看看make_pair函数的定义

image.png

这里就和我们设想的是一样的了,用于构建pair

然后我们看回去,他的参数有两个k和mapped_type(),这里的mapped_type实际上就是value的构造函数,因为在我们插入时只指定了key,没有value,因此直接调用value的构造函数即可

然后构造完成之后,返回的pair被插入到map中,返回值就是pair<iterator, bool>,这时我们取第一个iterator,表示指向插入的pair(无论是否成功插入,都会指向),然后再取第二个值,也就是插入之后的pair的value

返回值也就是pair之中的value

这里有个细节,重定义的返回值是引用的,说明可以支持赋值操作,初始化操作等

例如

map<string, string> m;
m["加"] = "plus";
m["减"] = "sub";
m["加"] = "add";
m["乘"];

总结一下就是分四步

  1. 用<key,value_type()>构建一个键值对,调用inset()插入到map中
  2. 如果key存在,插入失败,返回key所在位置的迭代器
  3. 如果key不存在,插入成功,返回新插入元素位置的迭代器
  4. 返回插入的键值对的引用

multiset

介绍

multiset文档

multiset与set类似,其中的元素是可以重复的,他的底层也是红黑树

红黑树是二叉搜索树,我们可以先按照二叉搜索树理解,他为什么也可以有序呢

实际上是因为他的插入规则是确定的,例如小于在左子树,大于等于在右子树,这样他的中序遍历就依然是有序的

multimap

multimap文档

multimap与map类似,需要注意的是,multimap不支持下标访问了,其他都是相同的

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaEE:网络初识

路由器VS交换机 组件局域网的方式是通过路由器或者交换机 交换机&#xff1a;上面有很多对接口&#xff0c;所有的口都是等价的&#xff0c;电脑可以连到任意的口上&#xff0c;连上的电脑就构成了局域网 路由器&#xff1a;又叫WiFi/猫 猫&#xff1a;调制解调器&#xff0…

全网最最最详细“Jupyter command ‘jupyter-notebook‘ not found.“的解决方案

"Jupyter command jupyter-notebook not found."。这通常意味着 jupyter-notebook 命令在当前的虚拟环境中未安装或未正确安装&#xff0c;因此系统无法识别此命令。 原因分析 未安装 Jupyter Notebook: 可能你的虚拟环境中还没有安装 Jupyter Notebook。虽然 Jupyt…

生存预后不显著?最佳阈值来帮你!| 附完整代码 + 注释

大家在进行生存预后分析时发现结果不显著&#xff0c;是不是当头一棒&#xff01;两眼一黑&#xff01;难不成这就代表我们的研究没意义吗&#xff1f;NONONO&#xff01;别慌&#xff01;说不定还有救&#xff01;快来看看最佳阈值能不能捞你一把&#xff01; 对生存分析感兴趣…

18. 查看帖子详情

文章目录 一、建立路由二、开发GetPostDetailHandler三、编写logic四、编写dao层五、编译测试运行 一、建立路由 router/route.go v1.GET("/post/:id", controller.GetPostDetailHandler)二、开发GetPostDetailHandler controller/post.go func GetPostDetailHand…

matplotlib系统学习记录

日期&#xff1a;2024.03.12 内容&#xff1a;将matplotlib的常用方法做一个记录&#xff0c;方便后续查找。 基本使用 # demo01 from matplotlib import pyplot as plt # 设置图片大小,也就是画布大小 fig plt.figure(figsize(20,8),dpi80)#图片大小&#xff0c;清晰度# 准…

机试:蛇形矩阵

问题描述: 代码示例: //蛇形矩阵 #include <bits/stdc.h> using namespace std;int main(){int n;cout << "输入样例" << endl; cin >> n;int k 1; for(int i 0; i < n; i){if( i %2 0){//单数行for(int j 0; j < n; j){ cout &…

网络计算机

TCP/IP四层模型 应用层&#xff1a;位于传输层之上&#xff0c;主要提供两个设备上的应用程序之间信息交换的服务&#xff0c;它定义了信息交换的格式&#xff0c;消息会交给下一层传输层来传递。我们把应用层交互的数据单元称为报文。应用层工作在操作系统的用户态&#xff0…

JS向指定位置添加元素

内容参考来源 splice方法 splice() 方法向/从数组中添加/删除项目&#xff0c;然后返回被删除的项目。 //在数组指定位置插入 var fruits ["Banana", "Orange", "Apple", "Mango"]; fruits.splice(2, 0, "Lemon", "…

26 easy 35. 搜索插入位置

//给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 // // 请必须使用时间复杂度为 O(log n) 的算法。 // // // // 示例 1: // // //输入: nums [1,3,5,6], …

C++之继承

目录 一、继承的关系 二、继承方式和子类权限 三、子类构造函数 四、继承的种类 一、继承的关系 继承一定要的关系&#xff1a;子类是父类 学生是人 狗是动物 继承的实现形式&#xff1a; class 子类名&#xff1a;继承方式 父类名 { 成员变量&#xff1a; 成员函数&a…

2024-03-13 作业

网络编程&#xff1a; 1.思维导图&#xff1a; 2.上课写的代码&#xff1a; 2.1网络字节序与主机字节序转换 运行代码&#xff1a; #include <myhead.h> int main() {int num 0x12345678;short int value 0x1234;int num_n htonl(num);int value_n htons(value);…

从汇编来角度剖析C语言函数调用过程

目录 1.引言 2.寄存器 3.栈帧 4.函数调用前调用者的动作 5.被调用者在函数调用后的动作 6.被调用者返回前的动作 7.调用者在返回后的动作 8.总结 1.引言 当一个c函数被调用时&#xff0c;一个栈帧(stack frame)是如何被建立&#xff0c;又如何被消除的。这些细节跟操作…