set类和map类介绍和简单使用

目录

set类介绍与简单使用

set类

multiset类

map类介绍与简单使用

map类

multimap类


set类介绍与简单使用

set类是一种关联式容器,在数据检索时比序列式容器效率更高。本质是一个常规的二叉搜索树,但是为了防止出现单支树导致效率下降进行了相关优化

set类也满足二叉搜索树的特点:

  1. 元素不重复:因此可以用来去重

  2. 默认中序遍历是升序

  3. 比较的平均次数为log_{2}{N}

  4. set中的元素不可以修改

  5. set中的底层使用二叉搜索树(红黑树)来实现

  6. 默认按照key升序排序

set类

使用set类需要包含头文件<set>

set官方文档

简单使用实例:

 #define _CRT_SECURE_NO_WARNINGS 1​#include <iostream>#include <set>using namespace std;​int main(){set<int> s;// 使用数组构造set,去重+排序int array[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0, 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };for (auto e : array){// 插入数据s.insert(e);}​// 使用正向迭代器遍历setset<int>::iterator it = s.begin();while (it != s.end()){cout << *it << " ";++it;}cout << endl;// 使用反向迭代器遍历setset<int>::reverse_iterator rit = s.rbegin();while (rit != s.rend()){cout << *rit << " ";++rit;}​cout << endl;​// 计数// set会去重,所以每一种数字只会出现1次cout << s.count(3) << endl;​// 查找+删除s.erase(s.find(3));// 范围for遍历for (auto e : s){cout << e << " ";}return 0;}

需要注意的两个函数lower_bound()upper_bound(),这两个函数放在一起的作用是获取到当前中序遍历的[lower_bound, upper_bound]区间

#define _CRT_SECURE_NO_WARNINGS 1​#include <iostream>#include <set>using namespace std;​int main(){set<int> s;// 使用数组构造set,去重+排序int array[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0, 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };for (auto e : array){// 插入数据s.insert(e);}// lower_bound与upper_boundset<int>::iterator it = s.lower_bound(3);while (it != s.upper_bound(8)){cout << *it << " ";++it;}return 0;}输出结果:3 4 5 6 7 8

首先解释lower_bound(3)的意思,在这个函数中,lower_bound()会取到第一个大于或者等于3的数值,返回其位置的迭代器,所以lower_bound(3)返回的是3所在位置的迭代器,接着upper_bound(8),对于upper_bound(8)会返回除8以外的比8大的数值位置的迭代器,也就是第一个大于8的数值位置的迭代器,所以上面的程序结果最后会输出8是因为取出了[3, 8]中的所有位于set容器中的值

multiset类

multiset类与set类不同的是,multiset类允许数据出现重复

multiset类官方文档

简单使用实例:

 #define _CRT_SECURE_NO_WARNINGS 1​#include <iostream>#include <set>using namespace std;​int main(){// 使用数组构造multiset,排序int array1[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0, 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };multiset<int> ms;for (auto num : array1){ms.insert(num);}​// 范围for遍历for (auto num : ms){cout << num << " ";}cout << endl;​// 统计3的次数cout << ms.count(3) << endl;​// lower_bound和upper_bound// 在multiset中会打印[第一个4, 最后一个4]中的所有4multiset<int>::iterator it = ms.lower_bound(4); while (it != ms.upper_bound(4)){cout << *it << " ";++it;}return 0;}

需要注意erase()函数在multiset中的两个用法有些许不同:

#define _CRT_SECURE_NO_WARNINGS 1​#include <iostream>#include <set>using namespace std;​int main(){int array2[] = { 1, 3, 5, 3, 3, 2, 4, 6, 8, 0, 1, 3, 3, 7, 9, 2, 4, 6, 3, 0 };multiset<int> ms1;for (auto num : array2){ms1.insert(num);}​for (auto num : ms1){cout << num << " ";}cout << endl;// 使用find查找后删除ms1.erase(ms1.find(3));for (auto num : ms1){cout << num << " ";}cout << endl;// 直接删除ms1.erase(3);for (auto num : ms1){cout << num << " ";}​return 0;}​输出结果:0 0 1 1 2 2 3 3 3 3 3 3 4 4 5 6 6 7 8 90 0 1 1 2 2 3 3 3 3 3 4 4 5 6 6 7 8 90 0 1 1 2 2 4 4 5 6 6 7 8 9

如果multiset中指定数值有重复,multiset类中find()函数会找到左子树第一个值为指定值(不存在则返回其他与指定值相同的节点)的位置,返回该位置的迭代器,所以此时调用erase()函数,将find()返回的迭代器传给erase()函数,删除的就是左子树的第一个值,而如果直接调用erase()函数,传入指定值,则一次性全部删除

map类介绍与简单使用

与set类不同的是,map类是KV模型的平衡二叉树(红黑树),因为是Key_Value模型,所以map类总是以key进行排序,map也是用来存储数据的,与序列式容器(forward_list)不同的是,其里面存储的是<key, value>结构的键值对pair

用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量keyvaluekey代表键值,value表示与key对应的信息。下面是SGI版本的键值对定义:

 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) {}​template <class U1, class U2>pair(const pair<U1, U2>& p) : first(p.first), second(p.second) {}};

map类的特点:

  1. 因为底层还是类似于二叉搜索树,但是进行了优化,所以效率为log_{2}{N}

  2. map类中的key值无法被修改,一旦插入了就没有再次修改的机会

  3. map类支持下标访问

  4. map类按照key升序排序

map类

map官方文档

简单使用实例:

map类没有直接添加key_value键值对的构造函数,所以需要使用其他方式进行内容添加

首先介绍map类中的insert()函数,与set类的insert()不同的是,map类需要使用pair对象作为参数传递给insert()函数,下面是insert()函数原型之一

 pair<iterator,bool> insert (const value_type& val);​// 其中value_type为pair<const key_type, mapped_type>// key_type为第一个模版参数Key// mapped_type为第二个模版参数T

所以在插入数据时,首先需要一个pair对象,前面提供了pair结构的原型,其中有三种构造函数

  1. 无参构造:firstsecond给类型初始值

  2. 有参构造:给定firstsecond对应的值进行初始化

  3. 拷贝构造:使用已经存在的pair对象构造

有了pair对象的构造,结合insert()函数就可以为map类添加对象,下面提供五种方式:

#define _CRT_SECURE_NO_WARNINGS 1​#include <iostream>#include <map>using namespace std;​int main(){// map的五种构造方式// 1. 创建pair对象再通过insert()函数插入到map中pair<string, string> p1("字符串1", "字符串2");map<string, string> m1;m1.insert(p1);​// 2. 匿名对象插入map<string, string> m2;m2.insert(pair<string, string>("字符串1", "字符串2"));​// 3. 无explicit修饰下的隐式类型转换map<string, string> m3;m3.insert({ "字符串1", "字符串2" });​// 4. make_pair函数map<string, string> m4;m4.insert(make_pair("字符串1", "字符串2"));​// 5. initializer_listmap<string, string> m5 = { {"字符串1", "字符串2"}, {"字符串3", "字符串4"} };​return 0;}

上面代码中的第三种方式与下面的过程等价

 pair<string, string> p2 = { "字符串1", "字符串2" }; // 隐式类型转换m3.insert(p2);

以二叉搜索树中:统计水果出现的次数为例

#include <iostream>#include <map>using namespace std;​int main(){​string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };map<string, int> m;// 插入数据for (auto str : arr){m.insert({str, 0});}​// 迭代器遍历auto it = m.begin();while (it != m.end()){cout << (*it).first << "->" << it->second << endl;++it;}cout << endl;// 查找+删除auto pos = m.find("苹果");m.erase(pos);auto it1 = m.begin();while (it1 != m.end()){cout << (*it1).first << "->" << it1->second << endl;++it1;}​return 0;}

需要注意map中的operator[]函数,如果想要实现在二叉搜索树中的计数,可以使用该函数

 #define _CRT_SECURE_NO_WARNINGS 1​#include <iostream>#include <map>using namespace std;​int main(){​string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };map<string, int> m;for (auto str : arr){m[str]++;}​auto it = m.begin();while (it != m.end()){cout << it->first << "->" << it->second << endl;++it;}​return 0;}

在map类中,operator[]函数的本质是通过[]中的key查找key对应的value值,如果key不存在就插入,将value设置为对应类型的默认值,如果key存在就返回value

这个函数的调用可以类比成下面的思路:

 (*((this->insert(make_pair(k,mapped_type()))).first)).second

将其拆解为三部分:

  1. (this->insert(make_pair(k,mapped_type())))

    该部分本质是调用了一个insert()函数,在map类中insert()函数返回pair<iterator, bool>,如果插入成功证明插入的键值对一开始不存在,返回插入后位置的迭代器,并将bool类型的变量设置为true表示插入成功;如果键值对一开始存在,返回存在的键值对位置的迭代器,并将bool类型的变量设置为false表示插入失败

  2.  (*(pair<iterator, bool>.first))

    该部分本质是调用插入节点的迭代器访问该迭代器的first值,因为这个键值对中的iterator存储的成功插入或者已经存在于map中的键值对位置的迭代器,所以该迭代器指向的是一个实际的节点,即一个实际的键值对节点,解引用该节点就可以取到其中的内容

  3.  (*iterator).second // iterator表示已经插入的节点或者原有节点位置的迭代器

    该部分就是取出迭代器指向的节点中的second的值

所以,在map类中operator[]可以用于下面的行为:

  1. 不存在[]中的key,插入该key

  2. 存在[]中的key,返回key对应的value

  3. 存在[]中的key,修改key对应的value

multimap类

与map类基本相同,但是multimap类允许数据出现重复,并且multimap类不支持operator[]函数和at函数

multimap官方文档

基本使用与map类和multiset类似,不再做演示

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

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

相关文章

【Linux】将IDEA项目部署到云服务器上,让其成为后台进程(保姆级教学,满满的干货~~)

目录 部署项目到云服务器什么是部署一、 创建MySQL数据库二、 修改idea配置项三、 数据打包四、 部署云服务器五、开放端口号六 、 验证程序 部署项目到云服务器 什么是部署 ⼯作中涉及到的"环境" 开发环境:开发⼈员写代码⽤的机器.测试环境:测试⼈员测试程序使⽤…

SQL面试题-留存率计算

表定义&#xff1a; create table if not exists liuliang_detail (user_id string comment ,record_time string comment yyyymmdd hh:mi:ss ) comment 流量明细表 ; 方法一&#xff1a; 计算的是整段时间范围内&#xff0c;每一天为基准的所有的留存1、2、7天的用户数。 …

WEB前端05-JavaScrip基本对象

JavaScript对象 1.Function对象 函数的创建 //方法一&#xff1a;自定义函数 function 函数名([参数]) {函数体[return 表达式] }//方法二&#xff1a;匿名函数 (function([参数]) {函数体[return 表达式] }); **使用场景一&#xff1a;定义后直接调用使用(只使用一次) (fun…

成为git砖家(1): author 和 committer 的区别

大家好&#xff0c;我是白鱼。一直对 git author 和 committer 不太了解&#xff0c; 今天通过 cherry-pick 的例子搞清楚了区别。 原理 例如我克隆了著名开源项目 spdlog 的源码&#xff0c; 根据某个历史 commit A 创建了分支&#xff0c; 然后 cherry-pick 了这个 commit …

《系统架构设计师教程(第2版)》第11章-未来信息综合技术-06-云计算(Cloud Computing) 技术概述

文章目录 1. 相关概念2. 云计算的服务方式2.1 软件即服务 (SaaS)2.2 平台即服务 (PaaS)2.3 基础设施即服务 (IaaS)2.4 三种服务方式的分析2.4.1 在灵活性2.4.2 方便性方 3. 云计算的部署模式3.1 公有云3.2 社区云3.3 私有云3.4 混合云 4. 云计算的发展历程4.1 虚拟化技术4.2 分…

python课设——宾馆管理系统

python课设——宾馆管理系统 数据库课设-宾馆管理系统-python3.7pyqt5 简介 大二数据库课程设计&#xff08;3-4天工作量&#xff09;的项目&#xff0c;登录界面的ui设计参考了他人成果&#xff0c;其余ui以及所有后端部分全部独立完成&#xff0c;详细功能见功能模块图使用…

防火墙NAT地址转换和智能选举综合实验

一、实验拓扑 目录 一、实验拓扑 二、实验要求&#xff08;接上一个实验要求后&#xff09; 三、实验步骤 3.1办公区设备可以通过电信链路和移动链路上网(多对多的NAT&#xff0c;并且需要保留一个公网IP不能用来转换) 3.2分公司设备可以通过总公司的移动链路和电信链路访…

简单爬虫案例

准备工作&#xff1a; 1. 安装好python3 最低为3.6以上&#xff0c; 并成功运行pyhthon3 程序 2. 了解python 多进程原理 3. 了解 python HTTP 请求库 requests 的基本使用 4. 了解正则表达式的用法和python 中 re 库的基本使用 爬取目标 目标网站&#xff1a; https://…

scrapy框架爬取豆瓣top250电影排行榜(下)

&#xff08;3&#xff09;在 pipeline.py 文件中对数据进行存储&#xff0c;此程序先写 入 txt 文件中&#xff0c;是为了判断该程序是否能正确爬取出数据。 此处使用了 json 库&#xff0c;使用 ensure_ascii False&#xff0c;能够确 保非 ASCII 字符&#xff08;如中文&am…

贪心算法(2024/7/16)

1合并区间 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。 示例 1&#xff1a; 输入&#xff1a;inter…

SpringCloud网关的实现原理与使用指南

Spring Cloud网关是一个基于Spring Cloud的微服务网关&#xff0c;它是一个独立的项目&#xff0c;可以对外提供API接口服务&#xff0c;负责请求的转发和路由。本文将介绍Spring Cloud网关的实现原理和使用指南。 一、Spring Cloud网关的实现原理 Spring Cloud网关基于Spring…

5.操作led

模版使用之前的hello驱动程序。 想要操作led&#xff0c;首先要找到原理图&#xff0c;查找GPIO对应的GPIO引脚 从图中能看出来LED2对应的GPIO是GPIO5_3&#xff0c;同时可以得知这个LED2是低电平点亮。查看cat /sys/kernel/debug/gpio可得知GPIO5_3&#xff08;第四组GPIO的第…

【深度学习入门篇 ⑧】关于卷积神经网络

【&#x1f34a;易编橙&#xff1a;一个帮助编程小伙伴少走弯路的终身成长社群&#x1f34a;】 大家好&#xff0c;我是小森( &#xfe61;ˆoˆ&#xfe61; ) &#xff01; 易编橙终身成长社群创始团队嘉宾&#xff0c;橙似锦计划领衔成员、阿里云专家博主、腾讯云内容共创官…

Python和C++骨髓细胞进化解析数学模型

&#x1f3af;要点 &#x1f3af; 数学模型邻接矩阵及其相关的转移概率 | &#x1f3af;蒙特卡罗模拟进化动力学 | &#x1f3af;细胞进化交叉图族概率 | &#x1f3af;进化图模型及其数学因子 | &#x1f3af;混合图模式对进化概率的影响 | &#x1f3af;造血干细胞群体的空间…

汇总国内镜像提供了Redis的下载地址

文章目录 1. 清华大学开源软件镜像站&#xff1a;2. 中国科技大学开源软件镜像&#xff1a;3. 阿里云镜像&#xff1a;4. 华为云镜像&#xff1a;5. 腾讯云镜像&#xff1a;6. 网易开源镜像站7. 官方GitHub仓库&#xff08;虽然不是镜像&#xff0c;但也是一个可靠的下载源&…

AI算法19-偏最小二乘法回归算法Partial Least Squares Regression | PLS

偏最小二乘法回归算法简介 算法概述 偏最小二乘法模型可分为偏最小二乘回归模型和偏最小二乘路径模型。其中偏最小二乘回归模型是一种新型的多元统计方法&#xff0c;它集中了主成分分析、典型相关分析和线性回归的特点&#xff0c;特别在解决回归中的共线性问题具有无可比拟…

# Redis 入门到精通(五)-- redis 持久化(2)

Redis 入门到精通&#xff08;五&#xff09;-- redis 持久化&#xff08;2&#xff09; 一、redis 持久化–save 配置与工作原理 1、RDB 启动方式&#xff1a;反复执行保存指令&#xff0c;忘记了怎么办&#xff1f;不知道数据产生了多少变化&#xff0c;何时保存&#xff1…

CNN之图像识别

Inception Inception网络是CNN发展史上一个重要的里程碑。在Inception出现之前&#xff0c;大部分流行CNN仅仅是把卷积层堆叠得越来越多&#xff0c;使网络越来越深&#xff0c;以此希望能够得到更好的性能。但是存在以下问题: 图像中突出部分的大小差别很大。由于信息位置的…

【typedb】例子:药物发现: studio运行

测试8:solution结果 测试1:获取名字为Q9NPB9的protein Let’s start by getting the names of the protein Q9NPB9:测试2:哪个基因编码了Q9NPB9 Now let’s see which gene encodes for protein Q9NPB9: 推理过程:

【Linux】基础I/O——FILE,用户缓冲区

1.FILE里的fd FILE是C语言定义的文件结构体&#xff0c;里面包含了各种文件信息。可以肯定的一点是&#xff0c;FILE结构体内一定封装了 fd 。为什么?来看接下来的思路分析&#xff1a; 1.使用系统接口的必然性   文件存储在磁盘上&#xff0c;属于外设。谁有权限访问…