关联式容器——map和set详解

troop主页
今日鸡汤:Never bend your head.Always hold it high.Look the world straight in the face.
加油!成为最好的编程大师

前言

我们前几篇文章讲了搜索二叉树,我们提到了搜索二叉树的应用就是K结构和KV结构,今天我们要提到的这两个关联式容器就是这两个结构的实现,废话少说直接今日我们的内容。

一,set

  1. set是按照一定次序存储元素的容器
  2. 在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的。
    set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们。
  3. 在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行
    排序。
  4. set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对
    子集进行直接迭代。
  5. set在底层是用二叉搜索树(红黑树)实现的。
    最后一点也是我们后面学习的重点。

1.1set的使用

在这里插入图片描述
这里的Compare就是比较大小,默认是按照小于的比较。
set的使用上没有太多可以讲的,他的绝大多数容器我们都是可以类比之前学习过的。
我们直接写一些代码来熟悉它。

	//去重+排序set<int> s;s.insert(2);s.insert(7);s.insert(7);s.insert(1);s.insert(10);s.insert(9);s.insert(14);s.insert(17);set<int>::iterator it = s.begin();while (it != s.end()){cout << *it << " ";it++;}cout << endl;

在这里插入图片描述
set就是二叉搜索树的K结构,她最基本就是排序+去重操作。
在这里插入图片描述
值得注意的是set的find,它的返回值是一个迭代器,并且当找不到这个数的时候返回的是set的最后一个位置,那么我们的代码就可以这样写。

	set<int>::iterator pos1 = s.find(7);if (pos1 != s.end()){cout << "找到了" << endl;}else{cout << "没有" << endl;}cout << endl;set<int>::iterator pos2 = s.find(100);if (pos2 != s.end()){cout << "找到了" << endl;}else{cout << "没有" << endl;}cout << endl;

在这里插入图片描述
同时set还有一个新的函数count
在这里插入图片描述
与find类似它也是查找,但他会返回这个数出现的次数,但是我们知道set是去重操作的,这个数最多一个。
这个函数是给multiset使用的。

特殊的set(multiset)

这个multiset就可以称得上真正的排序了,因为它只排序不去重

	multiset<int> s;s.insert(2);s.insert(7);s.insert(7);s.insert(7);s.insert(7);s.insert(7);s.insert(1);s.insert(10);s.insert(9);s.insert(14);s.insert(17);for (auto& e : s){cout << e << " ";}cout << endl;cout << s.count(7) << endl;

在这里插入图片描述
这里的count就发挥了他的作用了。

二,map

  1. map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元
    素。
  2. 在map中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的
    内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型
    value_type绑定在一起,为其取别名称为pair:
    typedef pair<const key, T> value_type;
  3. 在内部,map中的元素总是按照键值key进行比较排序的。
  4. map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序
    对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)。
  5. map支持下标访问符,即在[]中放入key,就可以找到与key对应的value。
  6. map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))。

2.2map的使用

在这里插入图片描述
在这里插入图片描述
map就是KV结构,C++这里的设计就是把KV一起放在一个结构体中去使用。
我们来看看map的插入。
在这里插入图片描述
注意看,insert的pair和上面的pair是两个不一样的pair,等会到[]我们会重点提到这个。
insert的插入方式有很多。

	map<string, string> dict;//匿名对象dict.insert(pair<string, string>("sort", "排序"));//有名对象pair<string, string> kv("string", "字符串");dict.insert(kv);//{}:c++11支持的隐式类型转换dict.insert({ "apple","苹果" });//make_pair:c++98dict.insert(make_pair("banana", "香蕉"));

我个人更喜欢make_pair这样的写法。

	map<string, string> dict;//匿名对象dict.insert(pair<string, string>("sort", "排序"));//有名对象pair<string, string> kv("string", "字符串");dict.insert(kv);//{}:c++11支持的隐式类型转换dict.insert({ "apple","苹果" });//make_pair:c++98dict.insert(make_pair("banana", "香蕉"));map<string, string>::iterator it = dict.begin();while (it != dict.end()){//cout << (*it).first << (*it).second << endl;//it->==pair*;pair->first   优化成一个->cout << it->first << it->second << endl;	++it;}

在这里插入图片描述
这里我们要说一说

cout << it->first << it->second << endl;
这里省略了一个->,他的完整操作是operator调用->,返回了数据的指针(pair*),然后pair*再调用->。这里优化成了一个箭头。

还有一点要注意:map里面看数据重不重复,只看key,只要key相同就构成冗余
同样的map也有一个支持冗余的就是:multimap

void map_test2()
{multimap<string, string> dict;dict.insert(pair<string, string>("sort", "排序"));dict.insert(pair<string, string>("sort", "12"));dict.insert(pair<string, string>("sort", "123"));dict.insert(pair<string, string>("sort", "1234"));for (auto& kv : dict){cout << kv.first<<":" << kv.second << endl;}
}

在这里插入图片描述

2.3

在这里插入图片描述

在这里插入图片描述
上面的翻译大致是:调用[]相当于调用这一大串。
在这里插入图片描述
==intsert中的pair的first指向了被插入元素所在位置的迭代器。

	string arr[] = { "香蕉","橘子","梨","苹果","草莓","香蕉","橘子", "香蕉","橘子", "香蕉","橘子", "香蕉","橘子","西瓜","榴莲" };map<string, int> countMap;for (auto& e : arr){pair<map<string, int>::iterator, bool> ret;ret = countMap.insert(make_pair(e, 1));//如果不存在那就直接插入,如果存在那这个inset什么事情都不会干,此时这里的bool值就是falseif (ret.second == false){//ret.first==iterator(被插入元素所在位置的迭代器),这个元素的second就是记录个数的ret.first->second++;}}

ret.first==iterator(被插入元素所在位置的迭代器);
理解了[]的原理,下标还是非常的好用的。上面这个统计次数的代码,用下标只要一行。

	for (auto& e : arr){countMap[e]++;}

总结

总的来说map和set就是我们已经学过的知识,知识换了包装而已,这里的重点就是要理解这个下标的原理,多通过代去深化自己的知识,下一节我们就要开始讲
AVL树和红黑树了。

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

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

相关文章

Vue3中的computed,watch和watchEffect的特点

1.computed 1&#xff09;computed拥有缓存性&#xff0c;多次调用会直接从缓存中获取&#xff0c;而不会重新执行&#xff0c;只有相依赖的数据发生改变才会重新计算&#xff0c;所以说computed性能很高。 例&#xff1a;下面是同时调用三次计算属性firstTotal和三次函数first…

扬帆出海扩规模,仍是比亚迪未来的发展关键?

又到了新能源车企公布阶段性成果的时期。 日前&#xff0c;乘联会预估2024年3月全国新能源乘用车厂商批发销量82万辆&#xff0c;同比增长33%&#xff0c;环比增长84%。其中&#xff0c;比亚迪继续领跑&#xff0c;3月销量超30万辆&#xff0c;环比增长147.8%&#xff0c;而这…

ABAP 的 AT NEW 语法

AT NEW一般用在LOOP里面。 当我们在LOOP里面处理数据的时候&#xff0c;经常要执行的是当一个字段值改变了&#xff0c;然后我们怎么怎么做。这个就是要用AT NEW。其实有点像分组。 解释起来就是&#xff0c;我有一个内表itab里面有很多行数据&#xff0c;我现在一条一条的lo…

简单用Nodejs + express 编写接口

文章目录 get接口示范post接口示范注意点 准备工作可以看上一篇文章&#xff1a;文章链接》》 get接口示范 app.get(/, (req, res) > {res.send("Hello World"); })因为是get接口&#xff0c;所以可以直接在浏览器上请求&#xff08;端口地址接口名&#xff09;…

测开面经(Git经典题目,Git入门)

1. GitHub是什么 a. Git是一个分布式版本控制系统&#xff0c;作用是跟踪、管理和协调软件开发项目中的代码更改。 b. 提供了一种有效的方式来管理代码的版本历史&#xff0c;以及多人协作开发的能力。 2. Git的作用有哪些 a. 版本控制&#xff1a;Git可以记录每次代码更改的…

基于51单片机轮胎胎压监测系统—数码管显示

基于51单片机轮胎胎压监测系统 &#xff08;仿真&#xff0b;程序&#xff0b;设计报告&#xff09; 功能介绍 具体功能&#xff1a; 1.MPX4115压力传感器胎压检测&#xff1b; 2.ADC0832进行模数转换后&#xff0c;51单片机处理控制&#xff1b; 3.数码管显示胎压&#xff…

想要品牌传播有效,先清楚这三个本质问题

在互联网时代&#xff0c;企业想要提高市场竞争力就需要做好品牌传播。然而有许多企业在做品牌传播时都会踩坑&#xff0c;原因是因为忽视了这三点&#xff0c;接下来就让媒介盒子和大家分享&#xff1a; 一、 文案本质是“购买理由” 在文案技巧中经常会出现一些词&#xff…

1. TypeScript: JavaScript 的超集,为大型应用而生

引言 在现代的前端开发领域&#xff0c;JavaScript 无疑是一门极其流行的语言。然而&#xff0c;随着前端项目的日益复杂&#xff0c;JavaScript 本身的一些特性使得维护和扩展大型代码库变得困难。这就是 TypeScript 应运而生的背景。TypeScript 是一种由微软开发的开源语言&…

java中如何使用Rabbitmq?

1、添加相关的依赖 在Java中使用RabbitMQ&#xff0c;你需要先确保RabbitMQ服务器已经安装并运行在你的机器上或者某个服务器上。然后&#xff0c;你需要在Java项目中添加RabbitMQ的Java客户端库作为依赖。对于Maven项目&#xff0c;你可以在pom.xml文件中添加以下依赖&#x…

SSL的起源和发展史

随着网络技术的发展&#xff0c;当前各大浏览器厂商都对尚未使用SSL证书&#xff0c;切换到HTTPS的网站做了风险预警。SSL证书的如此重要&#xff0c;你了解SSL证书的诞生和发展史吗&#xff1f;跟随本文一起来了解SSL的前世今生。 SSL协议的诞生 Netscape&#xff08;网景通…

uniapp 表单使用Uview校验 包括城市选择器

<view><!-- 注意&#xff0c;如果需要兼容微信小程序&#xff0c;最好通过setRules方法设置rules规则 --><u--form labelPosition"left" :model"model1" :rules"rules" ref"uForm" labelWidth"174"><u…

Python中csr_matrix的两种初始化方法

本文以csr_matrix为例来说明sparse矩阵的使用方法&#xff0c;其他类型的sparse矩阵可以参考https://docs.scipy.org/doc/scipy/reference/sparse.html csr_matrix是Compressed Sparse Row matrix的缩写组合&#xff0c;下面介绍其两种初始化方法 csr_matrix((data, (row_ind…

concat() 函数

concat(某一具体的值或数组对象) 作用&#xff1a;将括号里的内容连接在一起注意&#xff1a; &#xff08;1&#xff09;多个具体的值或数组对象用逗号隔开 &#xff08;2&#xff09;select 语句返回的结果也是个数组&#xff0c;所以 select 语句可以写在 concat 函数的括号…

【操作系统】-寄存器-具有记忆功能的元器件

为什么要使用寄存器 现代电子计算机用二进制来表示数字&#xff0c;人类发明了触发器&#xff0c;每个触发器可以保存1比特&#xff0c;为了保存一个较大的二进制数&#xff0c;组合一起就是新的元器件&#xff0c;称为寄存器&#xff08;register&#xff09;&#xff0c;或者…

Python读取文件里内容

如果要读取一个文件里的内容是 # 文件名&#xff1a;db.txt 1 2 3 4代码如下 import requests f open("db.txt", mode"rb") content f.read() f.close()data content.decode(utf-8)# 存到 list 里 data_list data.split(\r\n) print(data_list)# 结果…

Docker-部署、镜像容器管理、commit

安装部署 一、查询版本信息 命令说明docker version查看服务器与客户端版本docker info查看docker服务配置信息 二、安装部署 官网地址&#xff1a;Install Docker Engine | Docker Docs 1、卸载旧的版本 sudo yum remove docker \docker-client \docker-client-latest \…

MySQL-7.mysql约束

约束用于确保数据库中的数据满足特定的商业规则。 MySQL约束包含五种&#xff1a;not null、unique、primary key、foreign key、check 7.1 primary key 主键 字段名 字段类型 primary key 用于唯一的标识表的行数据&#xff0c;当定义主键约束后&#xff0c;该列不能重复。 pr…

力扣经典150题第九题:跳跃游戏

目录 1. 简介2. 问题描述3. 解题思路方法一&#xff1a;贪心算法 4. 算法实现方法一&#xff1a;贪心算法 5. 示例与测试6. 总结与展望7. 结语 1. 简介 本篇博客将讨论力扣经典150题中的跳跃游戏问题。给定一个非负整数数组 nums&#xff0c;数组中的每个元素代表在该位置可以…

perl 交叉编译

前言 Perl是一种高级、通用、解释型、动态的编程语言。Perl设计的初衷是为了更好地处理文本处理任务&#xff0c;但随着时间的发展&#xff0c;现在它已经变成了一种强大的一般目的编程语言。Perl支持面向过程和面向对象的编程风格。 Perl的特点&#xff1a; 强大的字符串处…

ROC与决策树介绍

ROC与决策树介绍 一、ROC介绍 ROC&#xff08;Receiver Operating Characteristic&#xff09;曲线&#xff0c;即受试者工作特征曲线&#xff0c;是一种用于评估二元分类器性能的工具。ROC曲线起源于信号检测理论&#xff0c;后来被广泛用于机器学习和统计学习中的分类问题。…