当前位置: 首页 > news >正文

【C++】map和set(一文拿捏,包教包会)

目录

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

2.键值对

3.树型结构的关联式容器

4.set

5.multiset

 6.map

 7.multimap


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

set:关联式容器——数据之间关联紧密

线性表(vector,list,deque):序列式容器——数据之间关联性基本为0

2.键值对

用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量,键值key和对应的信息val

比如现在想要统计十个成语出现的次数,那么成语这个字符串和他的次数就有紧密的一一对应关系

第一个模板参数是T1类型,就是key的类型,第二个是val的类型

键值对是一个类,T1和T2的类型允许不同,两个成员变量first和second都是公有的 

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实现了两种功能不同的管理式容器:树型结构和哈希结构

树形结构一般有四种:set,map,multiset,multimap

这四种容器的特点是:底层结构使用红黑树(平衡搜索二叉树),中序遍历是有序的

4.set

注意:
1. 与map/multimap不同,map/multimap中存储的是真正的键值对<key, value>,set中只放
value,但在底层实际存放的是由<value, value>构成的键值对
2. set中插入元素时,只需要插入value即可,不需要构造键值对。
3. set中的元素不可以重复(因此可以使用set进行去重)。
4. 使用set的迭代器遍历有序
5. set中的元素默认按照小于比较
6. set中查找某个元素,时间复杂度为:logn
7. set中的元素不允许修改:随意修改会破坏二叉搜索树的结构
8. set中的底层使用二叉搜索树(红黑树)来实现。

 并且看到最后一种初始化方式,set可以拷贝构造

set支持迭代器,也就是set支持范围for 

int main()
{int arr[] = { 0,12,3,4,5,65,7,1,4,1,4,7,4 };set<int> s1;for (auto e : arr){s1.insert(e);e++;}set<int> s2(s1);for (auto e : s2){cout << e << " ";e++;}return 0;
}

 很明显观察到,set:去重+排序

注意:set一般不喜欢用push,而是使用insert

5.multiset

他也在set的头文件,无需新加

他的功能从字面上就是可以允许重复元素

multiset:排序

其余和set没区别,只是set和multiset都有count函数,因为这个计算特殊val个数的函数在头文件<set>中,虽然计数对于set没啥用(因为去重),但是对于multiset还是很有用

 

int main()
{int arr[] = { 0,12,3,4,5,65,7,1,4,1,4,7,4 };multiset<int> s1;for (auto e : arr){s1.insert(e);e++;}multiset<int> s2(s1);for (auto e : s2){cout << e << " ";e++;}return 0;
}

那么允许重复怎么通过val找到位置,答案是找中序的第一个val 

那么set/multiset的find和算法库里面的find有什么区别?

肯定是原理不同,find是暴力查找,但是set.find()是按搜索树顺序查找,更快

 

 6.map

 清楚看到。map的类模板有key的类型,val类型和比较函数模板,还有空间适配器申请底层空间(现在不需要了解)

并且map中元素都是成对出现的,key值主要是用来排和唯一标识元素,而val值主要是存储key值的信息(这让我想起来法语的复合时态:etre/avoir+v. 第一个单词无实意,是用来表明时态的(过去或者将来之类的),而动词的用法常常表明意思),这一对组合起来构成map的成员类型,他是一个键值对

看两个函数 

说明lower_bound是闭区间 

upper_bound 是开区间

erase删除的区间也是左闭右开 

 

 这段代码的iulow是找小于等于'b'的元素,itup是指找大于‘d’的map中最小的元素

所以最后的结果是 

int main()
{std::map<char, int> mymap;std::map<char, int>::iterator itlow, itup;mymap['a'] = 20;mymap['b'] = 40;mymap['c'] = 60;mymap['d'] = 80;mymap['e'] = 100;itlow = mymap.lower_bound('b');  // itlow points to bitup = mymap.upper_bound('d');   // itup points to e (not d!)mymap.erase(itlow, itup);        // erases [itlow,itup)// print content:for (std::map<char, int>::iterator it = mymap.begin(); it != mymap.end(); ++it)std::cout << it->first << " => " << it->second << '\n';return 0;
}

看一下map是怎么使用的吧

int main()
{map<string, string> dict;dict.insert(pair<string,string>("string","字符串"));dict.insert(pair<string, string>("left", "左"));dict.insert(pair<string, string>("is", "是"));for (auto e : dict){cout << e.first << ":" << e.second << endl;}return 0;
}

但是这样每次自己写pair很繁琐,所以以后这种过程可以简化为

 这是自己创建map,那么对于一个数组,我想统计每一个字符串出现的次数怎么看呢

用一个find函数找map中是不是有e对应的字符串,find返回值是一个迭代器

迭代器的类型是value_type,上面说过就是map的key和val合起来的类型,就是pair类

 迭代器的second在我的Map就是int类型,用来记录每一个字符串出现次数 

int main()
{string s[] = { "苹果","香蕉","柿子","苹果","香蕉" ,"香蕉","柿子","香蕉" };map<string, int> Map;for (auto& e : s){auto it =Map. find(e);if (it == Map.end())Map.insert(make_pair(e, 1));elseit->second++;}for (auto e : Map){cout << e.first << ":" << e.second << endl;}return 0;
}

 但是这样写其实是笨笨的

因为map有一个很神奇的运算符重载,就是方括号[ ]

居然一排就搞定了,那么这个方括号的作用到底是什么?

 我们一起慢慢看这段文字

首先方括号的运算符重载函数的参数是key,返回值是val

也就是你传入一个key,我就给你他的val,并且返回引用,具体的值是用默认的构造函数构造的

那如果你给的key不在map里,我给你new一个key盛装你传过来的参数
 

并且他还贴心的告诉我们,有一个方括号同样功能的函数at,行为一样吗,只不过如果你传的key不在map,抛异常(老操作了,之前讲的很多支持下标随机访问的容器也都支持at,都是如果不成功那么抛异常)

最后看一下他给的一行奇怪原理

他说调用方括号函数的时候,是这样调用的

 肯定是从内往外看

首先他通过this指针调用insert函数,插入一个键值对,键值对的key就是你传过来的参数key,val的部分调用一个匿名构造 

 然后insert有返回值

 insert的返回值是一个键值对,这个键值对的第一个成员变量first会设置一个迭代器,指向新插入的元素,或者指向在map中有相同key的元素

第二个成员变量second被设置成bool类型,如果这个元素成功插入(原来map中没有key),second=true;否则(map存在key),second=false;

无论如何,insert的返回值就是一个键值对,也就橙色框现在是一个键值对,通过.的方式访问类的first成员变量(来到红色框)然后解引用,找到对应的second,返回second的值

验证一下我们的解释 

 当第一次遇到苹果,香蕉,柿子的时候,second都是false(0)

再遇到就变成true(1),因为map中已经有这三个字符串

小小总结这个强大的函数[ ]:

他有三层功能:插入,查找,修改

 7.multimap

允许相同的key存在多个不同的val

他的功能和map是一样的,但是他不支持[ ]

因为在multimap中一个key可能对应好多个val,通过first找second会乱套

他也给我们提供一个很好的思路——一个key可以对应多个val

int main()
{//multimap可以录入一个单词的不同意思multimap<string, string> dict;dict.insert(make_pair("left", "左边"));dict.insert(make_pair("left", "剩余"));dict.insert(make_pair("string", "字符串"));dict.insert(make_pair("left", "xxx"));for (const auto& kv : dict){cout << kv.first << ":" << kv.second << endl;}//同时map可以的功能(除了[ ])他也行/string arr[] = { "苹果", "西瓜", "香蕉", "草莓", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };multimap<string, int> countMap;for (auto& e : arr){//map<string, int>::iterator it = countMapauto it = countMap.find(e);if (it == countMap.end())countMap.insert(make_pair(e, 1));elseit->second++;}for (const auto& kv : countMap)cout << kv.first << ":" << kv.second << endl;return 0;
}

相关文章:

【C++】map和set(一文拿捏,包教包会)

目录 1.关联式容器和序列式容器 2.键值对 3.树型结构的关联式容器 4.set 5.multiset 6.map 7.multimap 1.关联式容器和序列式容器 set&#xff1a;关联式容器——数据之间关联紧密 线性表&#xff08;vector&#xff0c;list&#xff0c;deque&#xff09;&#xff1a;序…...

爬虫Day2 正则表达式

爬虫Day2 正则表达式 一、正则表达式 1. 正则的作用 正则表达式是一种可以让复杂的字符串变得简单的工具。 写正则表达式就是用正则符号来描述字符串规则 # 案例1&#xff1a;判断一个字符串是否是一个合法的手机号码 tel 23297293329# 方法1&#xff1a;不用正则 if len…...

LeetCode-0324~28

leetCode1032 思路&#xff1a;想的是维护一个后缀数组&#xff0c;然后用Set去判断一下&#xff0c;结果超时了&#xff0c;去看题解&#xff0c;好家伙AC自动机&#xff0c;没办法&#xff0c;开始学。 正确题解&#xff1a; class ACNode{public ACNode[] children;publi…...

Vue2自己封装的基础组件库或基于Element-ui再次封装的基础组件库,如何发布到npm并使用(支持全局或按需引入使用),超详细

最终效果如下 一、先创建vue2项目 1、 可以用vue-cli自己来创建&#xff1b;也可以直接使用我开源常规的vue2后台管理系统模板 以下我以 wocwin-admin-vue2 项目为例 修改目录结构&#xff0c;最终如下 2、修改vue.config.js文件 module.exports { // 修改 src 目录 为 exam…...

【开发】中间件——MongoDB

MongoDB是一个基于分布式&#xff08;海量数据存储&#xff09;文件存储的数据库。 MongoDB是一个介于关系数据库和非关系数据库之间的产品&#xff0c;是非关系数据库当中功能最丰富&#xff0c;最像关系数据库的&#xff0c;它支持的数据结构非常松散&#xff0c;是类似json…...

C++进阶 — 【C++11】

目录 一、 C11简介 二、 统一的列表初始化 1.&#xff5b;&#xff5d;初始化 2. initializer_list 三、声明 1. auto 2. decltype 3. nullptr 四、范围for循环 五、STL中一些变化 1. 提供了一些新容器 2.容器中增加了一些新方法 六、右值引用和移动语义 1. 左值引用和右…...

Mac安装Homebrew

1.前往Homebrew官网&#xff0c;复制官网的安装命令 https://brew.sh/ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"安装结束后&#xff0c;记得仔细看脚本执行最后的提示&#xff0c;需要我们复制两行命令执…...

【详细】利用VS2019创建Web项目,并发送到IIS,以及IIS与ASP.NET配置

一、打开VS2019选择创建新项目【最好以管理员身份运行VS2019&#xff0c;后面发布网站时需要以管理员身份&#xff0c;避免后面还要重启&#xff0c;可以一开始就以管理员身份运行】 二、选择语言为C#&#xff0c;然后选择“ASP.NET Web应用程序&#xff08;.NET Framework&…...

FasterRcnn,Yolov2,Yolov3中的Label Assignment机制 和 ATSS

一般把anchor到gt之间如何匹配的方法称为label assignment&#xff0c;也就是给预设的anchor打上正负样本等标签&#xff0c;方便我们后续进一步回归。 其实RPN和Yolo有各自的label assignment方法&#xff0c; 在Faster rcnn&#xff0c;yolo&#xff0c;RetinaNet中&#xf…...

使用Java技术WebSocket创建聊天、群聊,实现好友列表,添加好友,好友分组,聊天记录查询功能。

文章目录 引入依赖主要代码配置WebSocket创建通讯完整后台项目代码下载WebSocket的由来: 之前只有一个http协议,http协议是请求响应,存在缺陷,就是请求只能由客户端发起,然后请求到服务器,服务器做响应,但是如果服务器状态做了改变,客户端并不能即使的更新,之前的是按照…...

【Redis07】Redis基础:Bitmap 与 HyperLogLog 相关操作

Redis基础学习&#xff1a;Bitmap 与 HyperLogLog 相关操作继续进行 Redis 基础部分的学习&#xff0c;今天我们学习的是两种另外的数据类型。说是数据类型&#xff0c;但其实它们实际上使用的都是 String 类型做为底层基础&#xff0c;只不过是在存储的时候进行了一些特殊的操…...

华为路由器 VRRP主备配置

组网需求 如下图所示&#xff0c;PC1通过SW1双归属到R1和R2。为保证用户的各种业务在网络传输中不中断&#xff0c;需在R1和R2上配置VRRP主备备份功能。 正常情况下&#xff0c;主机以R1为默认网关接入Internet&#xff0c;当R1故障时&#xff0c;R2接替R1作为网关继续进行工作…...

docker容器安装ES

1.拉取镜像 docker pull elasticsearch:6.5.42.修改别名 docker tag [容器ID] es65:6.5.42.启动应用 docker run -it -d -p 9200:9200 -p 9300:9300 --name es -e ES_JAVA_OPTS"-Xms128m -Xmx128m" es65:6.5.43.拷贝配置文件到宿主机 docker cp es:/usr/share/ela…...

Python Module — prompt_toolkit CLI 库

目录 文章目录目录prompt_toolkit示例化历史记录热键自动补全多行输入Python 代码高亮自定义样式prompt_toolkit prompt_toolkit 是一个用于构建 CLI 应用程序的 Python 库&#xff0c;可以让我们轻松地构建强大的交互式命令行应用程序。 自动补全&#xff1a;当用户输入命令…...

springboot mybatis-plus 调用 sqlserver 的 存储过程 返回值问题

问题&#xff1a; 在使用 mybatis-plus 调用sqlserver 存储过程 没有返回值 经过资料查找 注意点 此处使用Map传参&#xff0c;原因在于存储过程的返回值&#xff0c;通常在参数定义中实现&#xff0c;如In 入参、out 出参。 这样当执行后有结果返回时&#xff0c;则可以将结…...

【0180】PG内核读取pg_hba.conf并创建HbaLine记录(1)

文章目录 1. pg_hba.conf文件是什么?2. postmaster何时读取pg_hba.conf?2.1 pg内核使用pg_hba.conf完成客户端认证的原理2.2 读取pg_hba.conf的几个模块3. pg内核读取pg_hba.conf过程3.1 VFD机制获取文件描述符3.2 根据fd读取文件内容相关阅读: 【0178】DBeaver、pgAdmin I…...

【原型设计工具】​​上海道宁为您提供Justinmind,助力您在几分钟内形成原型,并现场测试,无需编写任何代码

Justinmind是用于 Web和应用程序的原型制作工具 在几分钟内形成原型 并在现场进行测试 无需编写任何代码 单击一下即可轻松在线获取您的设计 并与整个团队共享 享受高效的沟通和快速反馈 以实现持续改进和利益相关者的支持 开发商介绍 JustinMind是由西班牙JustinMind公…...

计算机网络中---HDLP协议和PPP协议

目录 HDLC协议PPP协议HDLC协议和PPP协议HDLC协议 HDLC协议【高级数据链路控制协议】是一种数据链路层协议,用于在两个节点之间传输数据。以下是HDLC协议的重点知识: HDLC协议定义了一种标准的帧格式,包括起始标志、地址字段、控制字段、信息字段、校验字段和结束标志。HDLC…...

k8s之节点kubelet预留资源配置

k8s之kubelet预留资源配置1 前言2 预留资源Kube-reservedSystem-reservedEviction Thresholds实施节点可分配约束3 Pod优先级4 生产应用配置文件重启kubelet服务查看节点资源1 前言 最近k8s在使用过程中遇到这样一个问题 由于Pod没有对内存及CPU进行限制&#xff0c;导致Pod在…...

机器学习笔记之前馈神经网络(四)反向传播算法[数学推导过程]

机器学习笔记之前馈神经网络——反向传播算法[数学推导过程]引言回顾&#xff1a;感知机算法非线性问题与多层感知机反向传播算法(BackPropagation,BP\text{BackPropagation,BP}BackPropagation,BP)场景构建求解各权重更新量图示描述反向传播过程总结引言 上一节介绍了M-P\tex…...

Python爬虫实战:研究MechanicalSoup库相关技术

一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

ServerTrust 并非唯一

NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

认识CMake并使用CMake构建自己的第一个项目

1.CMake的作用和优势 跨平台支持&#xff1a;CMake支持多种操作系统和编译器&#xff0c;使用同一份构建配置可以在不同的环境中使用 简化配置&#xff1a;通过CMakeLists.txt文件&#xff0c;用户可以定义项目结构、依赖项、编译选项等&#xff0c;无需手动编写复杂的构建脚本…...