set和map的基本使用
目录
关联式容器
要点分析
键值对
pair介绍
set
模板参数列表:
set的构造:
常用接口
操作
multiset
map
map的构造
插入
make_pair
map的迭代器
operator[]
multimap
multimap中为什么没有重载operator[]
关联式容器
关联式容器也是用来存储数据的,和vector、list这样的序列式容器不同的是,它里面存储的是<key,value>结构的键值对,在数据检索时效率很高。在STL库中有两种不同结构的关联式容器,树形结构与哈希结构。树形结构的关联式容器包括set、multiset、map、multimap这四种,也是下面要谈论的主要内容。
要点分析
键值对
要走进关联式容器,首先要理解键值对的概念,这一概念在之前的文章中也有介绍,键值对是用来表示对应关系的结构,结构中一般包含两个成员变量key和value,key代表键值,value代表与之对应的信息。例如:下述图片中的名著和作者就是一一对应的关系!
pair介绍
pair这个类是对键值对的定义,将一对不同类型的数据组合(T1和T2)组合在一起,结构中包含两个成员变量分别是key和value,它们的类型是T1和T2。
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中只放value,但在底层实际存放的是由<value, value>构成的键值对。
模板参数列表:
●T: set中存放元素的类型,实际在底层存储<value, value>的键值对。
●Compare:set中元素默认按照小于来比较。
●Alloc:set中元素空间的管理方式,使用STL提供的空间配置器管理。
set的构造:
void TestSet3()
{//构造空的setset<int> s1;//根据区间构造setint arr[10] = {0,1,3,4,5,7,9,6,2,8};int size = sizeof(arr) / sizeof(int);set<int> s2(arr,arr+size);}
常用接口
修改操作
插入
void SetInsert()
{set<int> ss;ss.insert(5);ss.insert(3);ss.insert(2);ss.insert(2);ss.insert(4);ss.insert(2);ss.insert(2);for (auto& e : ss){cout << e << " ";}
}
需要注意的是,当要插入的数据已经存在,将不会继续插入。
删除
void Seterase()
{set<int> ss;ss.insert(1);ss.insert(2);ss.insert(3);ss.insert(4);ss.insert(5);for (auto& e : ss){cout << e << " ";}cout << endl;ss.erase(3);for (auto& e : ss){cout << e << " ";}cout << endl;ss.erase(5);for (auto& e : ss){cout << e << " ";}cout << endl;ss.erase(1);for (auto& e : ss){cout << e << " ";}
}
交换
void setswap()
{set<int> s1;s1.insert(1);s1.insert(3);s1.insert(5);s1.insert(7);s1.insert(9);cout << "交换前s1:";for (auto& e : s1){cout << e << " ";}set<int> s2;s2.insert(2);s2.insert(4);s2.insert(6);s2.insert(8);s2.insert(10);cout << endl;cout << "交换前s2:";for (auto& e : s2){cout << e << " ";}s1.swap(s2);cout << endl;cout << "交换后s1:";for (auto& e : s1){cout << e << " ";}cout << endl;cout << "交换后s2:";for (auto& e : s2){cout << e << " ";}
}
清理
void setclear()
{set<int> s1;s1.insert(2);s1.insert(4);s1.insert(6);s1.clear();
}
迭代器
void set_iterator()
{int arr[10] = {1,3,5,7,9,2,4,6,8,10};int size = sizeof(arr) / sizeof(int);set<int> s1(arr,arr+size);//auto it1 = s1.begin();set<int>::iterator it1 = s1.begin();while (it1 != s1.end()){cout << *it1 << " ";it1++;}//auto it2 = s2.rbegin()set<int>::reverse_iterator it2 = s1.rbegin();cout << endl;while (it2 != s1.rend()){cout << *it2 << " ";it2++;}
}
容量
void setempty_size()
{int arr[10] = { 1,3,5,7,9,2,4,6,8,10 };int size = sizeof(arr) / sizeof(int);set<int> s1(arr, arr + size);cout << "是否为空:" << s1.empty() << endl;cout << "有效元素个数:" << s1.size() << endl;s1.clear();cout << "是否为空:" << s1.empty() << endl;cout << "有效元素个数:" << s1.size() << endl;
}
操作
find:
void setfind()
{int arr[10] = { 1,3,5,7,9,2,4,6,8,10 };int size = sizeof(arr) / sizeof(int);set<int> s1(arr, arr + size);for (auto& e : s1){cout << e << " ";}cout << endl;auto it = s1.find(5);if (it != s1.end()){cout <<"找到了:" << *it << endl;}else{cout << "没找到!" << endl;}it = s1.find(100);if (it != s1.end()){cout << "找到了:" << *it << endl;}else{cout << "没找到!" << endl;}
}
count:
void setcount()
{int arr[10] = { 1,3,1,7,1,2,1,6,8,10 };int size = sizeof(arr) / sizeof(int);set<int> s1(arr, arr + size);for (auto& e : s1){cout << e << " ";}cout << endl;cout << s1.count(1) << endl;cout << s1.count(2) << endl;cout << s1.count(50) << endl;
}
对于count这个接口,你可能不太理解它为什么会存在,它好像只能确定数据是否出现过,查找数据已经有find了,好像没什么“用武之地”。哈哈哈,它的“志向”当然不在此处,我们接着向下看!
multiset
multiset在接口的用法上大致相同,相比较set而言multiset允许重复数据的出现:
void _multiset()
{int arr[10] = { 1,3,1,7,1,2,1,6,8,10 };int size = sizeof(arr) / sizeof(int);multiset<int> s(arr,arr+size);for (auto& e : s){cout << e << " ";}}
count接口上场:
void _multiset_count()
{int arr[10] = { 1,3,1,7,1,2,1,6,2,10 };int size = sizeof(arr) / sizeof(int);multiset<int> s(arr, arr + size);for (auto& e : s){cout << e << " ";}cout << endl;cout << s.count(1) << endl;cout << s.count(2) << endl;cout << s.count(10) << endl;
}
小问题:既然multiset允许数据的重复,那么当我们查找数据的时候,找到的是哪一个呢?
void _multiset_find()
{int arr[10] = { 1,3,1,7,1,2,3,6,3,10 };int size = sizeof(arr) / sizeof(int);multiset<int> s(arr, arr + size);for (auto& e : s){cout << e << " ";}cout << endl;multiset<int>::iterator it = s.find(3);while (it != s.end()){cout << *it << " ";it++;}
}
测试后发现,find找到的位置是中序遍历第一次找到的元素位置。其余接口和set的使用大多一样,这里就不在测试了。
map
●key: 键值对中key的类型
●T: 键值对中value的类型
map的构造
插入
查询文档了解到,insert的返回值是一个pair,需要的参数也是一个pair。
void maptest2()
{map<string, string> notepad;notepad.insert(pair<string,string>("张三","赤峰"));notepad.insert(pair<string,string>("李四","北京"));for (auto& e : notepad){cout << e.first << ":" << e.second << endl;}//auto pr = notepad.insert(pair<string, string>("王麻子", "西安"));pair<map<string,string>::iterator,bool> pr = notepad.insert(pair<string, string>("王麻子", "西安"));cout << (pr.first)->first <<":"<<(pr.first)->second<< endl;
}
接收insert后的返回值,并进行分析:
通过上述测试对insert有了大致的了解,但是插入的过程中代码显得好笨重,pair<string,string>......每次都要写好长好长,这个时候就要介绍一个帮我们偷懒的朋友了:make_pair!
make_pair
make_pair的返回值是一个pair,根据模板参数T1,T2确定pair中两个元素的类型,根据参数x,y确定元素值。也就是说在上述代码插入数据的部分可以这样写:
map<string, string> s;
s.insert(make_pair("张小红","内蒙古"));
map的迭代器
void mapTest4()
{map<string, string> notepad;notepad.insert(make_pair("张三", "赤峰"));notepad.insert(make_pair("李四", "北京"));notepad.insert(make_pair("王麻子", "西安"));notepad.insert(make_pair("张小红", "内蒙古"));map<string, string>::iterator it1 = notepad.begin();cout << "-----------正向迭代器-----------" << endl;while (it1 != notepad.end()){//cout << (*it1).first << ":" << (*it1).second << endl;cout << it1->first << ":" << it1->second << endl;it1++;}cout << "-----------反向迭代器-----------" << endl;map<string, string>::reverse_iterator it2 = notepad.rbegin();while (it2 != notepad.rend()){//cout << (*it2).first << ":" << (*it2).second << endl;cout << it2->first << ":" << it2->second << endl;it2++;}
}
operator[]
operator[]重载和以往的[]重载相比有一些不一样,传过来的参数是key,返回值是value。在这过程中,首先向this插入make_pair,insert的返回值类型又是一个pair<iterator,bool>,访问pair的first元素获取到一个迭代器,迭代器找到的位置又是一个pair<key,value>,返回该pair的第二个元素也就是value。
观察上图分析后,[]除了访问元素外,还能进行查找,修改,插入的操作。
void mapTest5()
{map<string,int> grade;//插入,前提是该数据原来并不存在grade["语文"];//[]返回值是value,可以对其进行修改grade["语文"] = 99;//查找,根据key查找对应的valuecout << grade["语文"] << endl;
}
应用场景1:统计“象牙山村”选举票数!
void mapset1()
{map<string, int> count;string arr[10] = {"刘能","谢广坤","谢广坤","赵四","王老七","刘能","刘能","王老七","刘能","谢广坤"};for (auto& e : arr){auto it = count.find(e);if (it == count.end()){//插入count.insert(make_pair(e,1));}else{//(*it).second++;it->second++;}}cout << "-------象牙山选举大会--------" << endl;for (auto& e : count){cout << e.first << ":" << e.second <<"票"<< endl;}
}
使用[]的版本:
void maptest1()
{map<string, int> count;string arr[10] = {"刘能","谢广坤","谢广坤","赵四","王老七","刘能","刘能","王老七","刘能","谢广坤"};for (auto& e : arr){count[e]++;}cout << "-------象牙山选举大会--------" << endl;for (auto& e : count){cout << e.first << ":" << e.second <<"票"<< endl;}
}
对比两组代码,后者是不是简单了不少呢,[]使用起来非常的方便,但同时也是一把双刃剑,需要我们对其底层原理有所了解,在使用的时候也一定要细心。
multimap
multimap和map的区别:map中的key是唯一的,而multimap中key是可以重复的。
void Test6()
{multimap<string, string> dict;dict.insert(make_pair("左边", "left"));dict.insert(make_pair("左边", "LEFT"));dict.insert(make_pair("左边", "****"));
}
multimap中为什么没有重载operator[]
在了解过map的[]重载后,你知道[]需要key来访问value。那么在multimap这种允许key重复出现的场景下,xxx[key]访问到的value不一定是唯一的,这时的修改操作也不知道该去修改哪一个value,所以multimap没有重载[]。
小结:关联式容器的介绍到这就结束了,有些接口没有涉及到,有兴趣的小伙伴可以继续查找文档探索!
<set> - C++ Reference
<map> - C++ Reference
相关文章:
set和map的基本使用
目录 关联式容器 要点分析 键值对 pair介绍 set 模板参数列表: set的构造: 常用接口 操作 multiset map map的构造 插入 make_pair map的迭代器 operator[] multimap multimap中为什么没有重载operator[] 关联式容器 关联式容器也是用…...
已解决pip install wxPython模块安装失败
已解决(pip install wxPython安装失败)error: legacy-instal1-failure Encountered error while trying to install package.wxPython note: This is an issue with the package mentioned above,not pip. hint : See above for output from …...
Linux基础——连接Xshell7
个人简介:云计算网络运维专业人员,了解运维知识,掌握TCP/IP协议,每天分享网络运维知识与技能。座右铭:海不辞水,故能成其大;山不辞石,故能成其高。个人主页:小李会科技的…...
C++——智能指针1
目录 RAII auto_ptr模拟实现 智能指针拷贝问题 唯一指针 shared_ptr(可以拷贝) shared_ptr模拟实现 完整代码 循环引用 weak_ptr模拟实现 定制删除器 shared_ptr定制删除器模拟实现 内存泄漏 RAII RAII(Resource Acquisit…...
[数据集][VOC][目标检测]翻越栏杆翻越防护栏数据集目标检测可用yolo训练-1035张介绍
数据集格式:Pascal VOC格式(不包含分割路径的txt文件和yolo格式的txt文件,仅仅包含jpg图片和对应的xml) 图片数量(jpg文件个数):1035 标注数量(xml文件个数):1035 标注类别数:2 标注类别名称:["fylg","…...
深度学习 | BN层原理浅谈
深度学习 | BN层原理浅谈 文章目录深度学习 | BN层原理浅谈一. 背景二. BN层作用三. 计算原理四. 注意事项为什么BN层一般用在线性层和卷积层的后面,而不是放在激活函数后为什么BN能抑制过拟合(有争议)一. 背景 神经网络在训练时,由于内存限制࿰…...
每日面试题
2022/12/15 如何实现一个IOC容器 1、配置文件配置包扫描路径 2、递归包扫描获取.class文件 3、反射、确定需要交给lOC管理的类4、对需要注入的类进行依赖注入 配置文件中指定需要扫描的包路径 定义一些注解,分别表示访问控制层、业务服务层、数据持久层、依赖注…...
将IDEA的项目托管到gitee
目录1. 在gitee上创建仓库2. 本地创建仓库目录3. 将项目添加到缓冲区4. 将缓冲区的项目添加到本地仓库5. 将本地仓库的项目上传到gitee6. 遇到的问题6.1 问题描述6.2 解决方法7. 相关图示与补充8. 相关参考1. 在gitee上创建仓库 2. 本地创建仓库目录 在IDEA中选择创建 Git 仓…...
父类子类静态代码块、构造代码块、构造方法执行顺序
github:https://github.com/nocoders/java-everything.git 名词解释 静态代码块:java中使用static关键字修饰的代码块,每个代码块只会执行一次,JVM加载类时会执行静态代码块中的代码,静态代码块先于主方法执行。构造代码块&#…...
【C++】开散列实现unordered_map与unordered_set的封装
本文主要介绍unordered_map与unordered_set的封装,此次封装主要用上文所说到的开散列,通过开散列的一些改造来实现unordered_map与unordered_set的封装 文章目录一、模板参数二、string的特化三、正向迭代器四、构造与析构五、[]的实现六、unordered_map的实现七、u…...
华为OD机试真题Python实现【删除指定目录】真题+解题思路+代码(20222023)
删除指定目录 题目 某文件系统中有 N 个目录, 每个目录都一个独一无二的 ID。 每个目录只有一个付目录, 但每个目录下可以有零个或多个子目录, 目录结构呈树状结构。 假设 根目录的 ID 为0,且根目录没有父目录 ID 用唯一的正整数表示,并统一编号 现给定目录 ID 和其付目…...
CSS选择器大全(上)
基础选择器: id选择器:#id{} 类选择器: .class{} 标签选择器: h1{} 复合选择器: 交集选择器:作用:选中同时符合多个条件的元素 语法:选择器1选择器2选择器3选择器n{} 注意ÿ…...
JavaScript 俄罗斯方块 - setTimeout和rAF
本节内容需要有些基础知识,如进程和线程,队列数据结构 一、setTimeout和setInterval 只要使用过JavaScript的朋友,对setTimeout和setInterval应该不会默生,如果光说怎样去使用这个API,并不难,无非就是隔多少毫秒再执行某个函数,把变化的内容封装在函数中,就可以制作出动…...
LeetCode:构造最大二叉树;使用中序和后序数组构造二叉树;使用前序和中序数组遍历二叉树。
构造二叉树最好都是使用前序遍历;中左右的顺序。 654. 最大二叉树 中等 636 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点,其值为 nums 中的最大值。递归地在最大值 左边 的 子数组前缀上 构建…...
nodejs实现jwt
jwt是json web token的简称,本文介绍它的原理,最后后端用nodejs自己实现如何为客户端生成令牌token和校验token 1.为什么需要会话管理 我们用nodejs为前端或者其他服务提供resful接口时,http协议他是一个无状态的协议,有时候我们…...
结构体占用内存大小如何确定?-->结构体字节对齐 | C语言
目录 一、什么是结构体 二、为什么需要结构体 三、结构体的字节对齐 3.1、示例1 3.2、示例2 3.3、示例3 3.4、示例4 3.5、示例5 四、结构体字节对齐总结 一、什么是结构体 结构体是将不同类型的数据按照一定的功能需 求进行整体封装,封装的数据类型与大小均…...
Vue和Uniapp:优缺点比较
Vue和Uniapp是两个流行的前端框架,都是用于开发跨平台应用程序的工具。虽然两者都有很多相似之处,但它们也有一些不同之处,这些不同之处可以影响你的选择。下面将对Vue和Uniapp的优缺点进行比较和分析,以帮助你做出更明智的决策。…...
AMBA-AXI(二)AXI的序,保序与乱序
💡Note:本文是根据AXI协议IHI0022F_b_amba_axi_protocol_spec.pdf(issue F)整理的。主要是分享AXI3.0和4.0部分。如果内容有问题请大家在评论区中指出,有补充或者疑问也可以发在评论区,互相学习ὤ…...
APIs and Open Interface--非工单领、发料(含调拨)
表名 MTL_TRANSACTIONS_INTERFACEMTL_TRANSACTION_LOTS_INTERFACE序列 MTL_MATERIAL_TRANSACTIONS_S.NEXTVALAPIs INV_TXN_MANAGER_PUB.PROCESS_TRANSACTIONS案例 杂发/杂收(代码)Declare v_user_id number : fnd_global.user_id; v_login_id number …...
互联网医院系统软件开发|互联网医院管理系统开发的好处
互联网医院一直是现在的热门行业,很多的医院已经开发了互联网医院,并且已经在良好的运行中,而有一些医院和企业正在开发中,或者打算开发互联网医院系统,其实这些企业和医院还是很有远见的,因为他们知道并了…...
2.单例模式
基本概念 单例模式:保证一个类只有一个实例,并提供一个访问该实例的全局访问点 常见应用场景 读取配置文件的类一般设计为单例模式网站计数器应用程序的日志应用,因为共享日志文件一直处于打开状态,只能有一个实例去操作Spring…...
【保姆级】Java后端查询数据库结果导出xlsx文件+打印xlsx表格
目录前言一、需求一:数据库查询的数据导出成Excel表格1.1 Vue前端实现导出按钮点击事件1.2 后端根据数据库查询结果生成xlsx文件二、需求二:对生成的xlsx文件调用打印机打印2.1 Vue前端实现按钮事件2.2 后端实现打印前言 最近在弄一个需求,需…...
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)
文章目录1 JDBC(Java Database Connectivity)1.1 什么是 JDBC?1.2 JDBC 核心思想2 JDBC开发步骤【重点】2.0 环境准备2.1 注册数据库驱动2.2 获取数据库的连接2.3 获取数据库操作对象Statement2.4 通过Statement对象执行SQL语句2.5 处理返回结…...
vue3生命周期
一、Vue3中的生命周期 1、setup() : 开始创建组件之前,在 beforeCreate 和 created 之前执行,创建的是 data 和 method 2、onBeforeMount() : 组件挂载到节点上之前执行的函数; 3、onMounted() : 组件挂载完成后执行的函数; 4、…...
Python学习笔记10:开箱即用
开箱即用 模块 python系统路径 import sys, pprint pprint.pprint(sys.path) [,D:\\Program Files\\Python\\Lib\\idlelib,D:\\Program Files\\Python\\python310.zip,D:\\Program Files\\Python\\DLLs,D:\\Program Files\\Python\\lib,D:\\Program Files\\Python,D:\\Progr…...
详解JAVA反射
目录 1.概述 2.获取Class对象 3.API 3.1.实例化对象 3.2.方法 3.3.属性 1.概述 反射,JAVA提供的一种在运行时获取类的信息并动态操作类的能力。JAVA反射允许我们在运行时获取类的属性、方法、构造函数等信息,并能够动态地操作它们。 2.获取Class…...
在nestjs中进行typeorm cli迁移(migration)的配置
在nestjs中进行typeorm cli迁移(migration)的配置 在学习nestjs过程中发现typeorm的迁移配置十分麻烦,似乎许多方法都是旧版本的配置,无法直接使用. 花了挺长时间总算解决了这个配置问题. db.config.ts 先创建db.config.ts, 该文件export了两个对象,其…...
前端工程构建问题汇总
1.less less-loader安装失败问题 npm install less-loader --save --legacy-peer-deps 加上–legacy-peer-deps就可以了 在NPM v7中,现在默认安装peerDependencies,这会导致版本冲突,从而中断安装过程。 –legacy-peer-deps标志是在v7中引…...
某马程序员NodeJS速学笔记
文章目录前言一、什么是Node.js?二、fs文件系统模块三、Http模块四、模块化五、开发属于自己的包模块加载机制六、Express1.初识ExpressGET/POSTnodemon2.路由模块化3.中间件中间件分类自定义中间件4. 跨域问题七、Mysql模块安装与配置基本使用Web开发模式Session认证JWT八、m…...
SpringMVC DispatcherServlet源码(6) 完结 静态资源原理
阅读源码,分析静态资源处理器相关组件: 使用SimpleUrlHandlerMapping管理url -> 处理器映射关系spring mvc使用WebMvcConfigurationSupport注入SimpleUrlHandlerMapping组件DelegatingWebMvcConfiguration可以使用WebMvcConfigurer的配置静态资源url…...
做擦边网站 服务器/google免登录网页版
课程首页地址:http://blog.csdn.net/sxhelijian/article/details/7910565,本周题目链接:http://blog.csdn.net/sxhelijian/article/details/8635385【项目3-用结构体数组作计算】接项目2,(1)从文件中读出数…...
家居行业网站建设/网络广告策划的步骤
Description 草原上住着一群小松鼠,每个小松鼠都有一个家。时间长了,大家觉得应该聚一聚。但是草原非常大,松鼠们都很头疼应该在谁家聚会才最合理。 每个小松鼠的家可以用一个点 \((x,y)\) 表示,两个点的距离定义为点 \((x,y)\) 和…...
深圳英文网站设计/广州网站营销seo费用
存储基础知识三 文件系统 2009-10-09 17:32:58标签:存储 文件系统 [推送到技术圈] 一、概述文件系统定义了把文件存储于磁盘时所必须的数据结构及磁盘数据的管理方式。我们知道,磁盘是由很多个扇区(Sector)组成的ÿ…...
新品发布会策划/青岛网站优化公司哪家好
准备工作:gitup或者码云(gitee)案例:码云上操作(gitup是一样的)一.项目组老大任务1.创建组织,添加小组开发成员入组2.创建仓库3.创建分支(主分支master不需要手动创建)二.组员任务组员的任务当然毋庸置疑是项目开发了1.从项目地址下载远程主分支(master)git clone ssh地址||git…...
做网站的主要作用/网站建设的基本流程
皮尔逊Pearson 相关系数:使用前提:大小一致、连续、服从正态分布的数据集;斯皮尔曼spearman等级相关系数:皮尔逊Pearson 相关系数使用前提任何一个条件不满足时可以考虑使用该系数;肯德尔等级kendallta相关系数&#x…...
阿里企业邮箱客服/搜索引擎外部链接优化
花了近一天的时间,总算把Lenovo-Vista-Chs-Rdvd-Um下载完(2.45G),刻盘后安装系统。安装过程中没碰到什么问题,但第一次久未进入系统,起初认为是系统仍要作初始化之类的工作,等了很长时间未见反应…...