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://xiahunao.cn/news/3246908.html

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

相关文章

Linux 命令 —— top命令(查看进程资源占用)

文章目录 top 命令显示信息介绍top 命令使用 top 命令显示信息介绍 top 命令是 Linux/Unix 系统中常用的进程监控工具&#xff0c;可以实时动态显示系统中各个进程的资源占用情况&#xff0c;包括CPU、内存等。 进入 linux 系统&#xff0c;直接输入 top&#xff0c;回车&…

2014-2024年腾势D9N7N8EVDMI维修手册和电路图资料线路图接线图

经过整理&#xff0c;2014-2024年腾势汽车全系列已经更新至汽修帮手资料库内&#xff0c;覆盖市面上99%车型&#xff0c;包括维修手册、电路图、新车特征、车身钣金维修数据、全车拆装、扭力、发动机大修、发动机正时、保养、电路图、针脚定义、模块传感器、保险丝盒图解对照表…

中国星坤X0800HI系列线对板连接器:创新技术连接,引领智能家居未来!

近日&#xff0c;中国星坤推出的X0800HI系列线对板连接器&#xff0c;凭借其独特的设计和卓越的性能&#xff0c;引起了业界的广泛关注。 X0800HI系列线对板连接器在极小空间内实现了线对板的W-B连接&#xff0c;这不仅解决了传统连接方式中剥线和焊接的繁琐步骤&#xff0c;还…

Seata源码分析 全局事务开启提交回滚流程

文章目录 Seata全局事务源码Seata AT模式的设计思路源码入口TransactionalTemplate开启全局事务TM开启全局事务TC处理TM的请求 全局事务提交微服务端TM发送请求TC处理TM的请求RM处理TC的请求 全局事务回滚TM发送请求TC处理TM的请求RM处理TC的请求 补充知识微服务怎么找TC服务 S…

配置三层链路聚合增加链路带宽并提高可靠性的示例

规格 适用于所有版本的AR路由器。 AR161、AR161W、AR169、AR161G-L不支持该示例。 组网需求 在某小型企业网环境中部署了两台AR路由器Router_1和Router_2&#xff0c;Router_1作为用户接入设备&#xff0c;Router_2作为网络接入设备。为了保证用户的带宽&#xff0c;当用户量…

【Kaggle】练习赛《保险交叉销售的二分类预测》

前言 本篇文章介绍的是Kaggle月赛《Binary Classification of Insurance Cross Selling》&#xff0c;即《保险交叉销售的二元分类预测》。这场比赛非常适合作为机器学习入门者的实践练习。在之前的几期练习赛中&#xff0c;我们从多个角度详细讲解了探索性数据分析&#xff0…

爆火出圈的Robotaxi,会是自动驾驶的最优解吗?

八年前&#xff0c;百度决定投资无人驾驶时&#xff0c;李彦宏说&#xff1a;“它是人工智能最顶级的工程&#xff0c;将彻底改变人类的出行和生活。” 八年后&#xff0c;萝卜快跑从理想变成现实&#xff0c;奔跑在全国各地的街头&#xff0c;诠释了什么叫“科技不该高高在上…

2.javaWeb_请求和响应的处理(Request,Response)

2.请求和响应的处理 文章目录 2.请求和响应的处理一、动态资源和静态资源javax.servlet(包) 二、Servlet体系1.简介2.HttpServlet3.Servlet生命周期 三、Request对象1.ServletRequest1)ServletRequest主要功能有&#xff1a;2)ServletRequest类的常用方法: 2.HttpServletReques…

72B大模型分片部署

一、定义 目的官方教程案例小模型修改device_map 方式二 二、实现 目的&#xff1a; 将72B大模型 部署到2张gpu 显卡中。官方教程 帖子&#xff1a;https://huggingface.co/blog/accelerate-large-models实现 1. 自动部署 model AutoModelForCausalLM.from_pretrained(mod…

JUC 包中的 Atomic 原子类总结

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

【Java数据结构】初始线性表之一:链表

为什么要有链表 上一节我们描述了顺序表&#xff1a;【Java数据结构】初识线性表之一&#xff1a;顺序表-CSDN博客 并且进行了简单模拟实现。通过源码知道&#xff0c;ArrayList底层使用数组来存储元素。 由于其底层是一段连续空间&#xff0c;当在ArrayList任意位置插入或者…

Linux shell编程学习笔记64:vmstat命令 获取进程、内存、虚拟内存、IO、cpu等信息

0 前言 在系统安全检查中&#xff0c;通常要收集进程、内存、IO等信息。Linux提供了功能众多的命令来获取这些信息。今天我们先研究vmstat命令。 1.vmstat命令的功能、用法、选项说明和注意事项 1.1 vmstat命令的功能 vmstat是 Virtual Meomory Statistics&#xff08;虚拟内…

4.作业--Jquery,JS

目录 作业题目&#xff1a;1.使用Jquery完成点击图片变换图片颜色 A图 B代码 HTML的部分 JQ的部分 作业题目&#xff1a;2.使用JS中的DOM操作完成背景颜色渐变方向变换。点击背景&#xff0c;渐变方向发生改变。 A图 B代码 学习产出&#xff1a; 作业题目&#xff1a;1…

封装网络请求 鸿蒙APP HarmonyOS ArkTS

一、效果展示 通过在页面直接调用 userLogin(params) 方法&#xff0c;获取登录令牌 二、申请网络权限 访问网络时候首先需要申请网络权限&#xff0c;需要修改 src/main 目录下的 module.json5 文件&#xff0c;加入 requestPermissions 属性&#xff0c;详见官方文档 【声明权…

深度学习Week20——Pytorch实现残差网络和ResNet50V2算法

文章目录 深度学习Week20——Pytorch实现残差网络和ResNet50V2算法 一、前言 二、我的环境 三、代码复现 3.1 配置数据集 3.2 构建模型 四、模型应用与评估 4.1 编写训练函数 4.2 编写测试函数 4.3 训练模型 4.4 结果可视化 一、前言 &#x1f368; 本文为&#x1f517;365天深…

昇思25天学习打卡营第 12 天 | mindspore 实现 ResNet50 图像分类

1. 背景&#xff1a; 使用 mindspore 学习神经网络&#xff0c;打卡第 12 天&#xff1b;主要内容也依据 mindspore 的学习记录。 2. ResNet 介绍&#xff1a; mindspore 实现 ResNet50 图像分类&#xff1b; ResNet 基本介绍&#xff1a; Residual Networks 是微软研究院 K…

港股指数实时行情API接口

港股 指数 实时 行情 API接口 # Restful API https://tsanghi.com/api/fin/index/HKG/realtime?token{token}&ticker{ticker}指定指数代码&#xff0c;获取该指数的实时行情&#xff08;开、高、低、收、量&#xff09;。 更新周期&#xff1a;实时。 请求方式&#xff1a…

GuLi商城-商品服务-API-属性分组-分组修改级联选择器回显

前端代码:略 后端回显接口: 递归方法: @Override publi

linux进程——父子进程层面的PID,fork的原理与理解

前言&#xff1a;本篇内容主要讲解进程中系统调用fork和父子进程的概念与原理&#xff0c; 想要系统学习linux进程的友友们只管看本篇文章是不行的。 还要学习一些linux进程的周边知识以及linux进程其他方面的知识&#xff0c;博主的linux专栏中已经加入了这些文章方便友友们进…

连锁零售门店分析思路-人货场 数据分析

连锁零售门店分析思路 以下是一个连锁零售门店的分析思路&#xff1a; 一、市场与竞争分析 二、门店运营分析&#xff08;销售分析&#xff09; 三、销售与财务分析 四、客户分析 五、数字化与营销分析 最近帮一个大学生培训&#xff0c;就门店销售分析 &#xff0c;说到门店…