【C++】学习笔记——map和set

文章目录

  • 十五、map和set
    • 1. 关联式容器
    • 2. set的介绍
    • 3. set的使用
    • 4. multiset
    • 5. map的介绍
    • 6. map的使用
    • 7. multimap
    • 8. map中重载的operator[]
  • 未完待续


十五、map和set

1. 关联式容器

我们已经接触过STL中的部分容器,比如:vectorlistdeque 等,这些容器统称为 序列式容器序列式容器底层的数据结构里面存储的是元素本身。
关联式容器也是用来存储数据的,与序列式容器不同的是,其 里面存储的是<key, value>结构的键值对 ,即底层的数据结构包含两个值,key代表键值value代表与key对应的信息

在数据检索时关联式容器比序列式容器效率更高。

而set和map就是STL中的 树形结构的关联式容器 。底层是平衡二叉树(红黑树)。

2. set的介绍

set文档

3. set的使用

使用set记得包含 set 头文件哦。
在这里插入图片描述
在这里插入图片描述

#include<iostream>
#include<set>
using namespace std;void test01()
{set<int> s;s.insert(5);s.insert(2);s.insert(4);s.insert(1);s.insert(3);s.insert(2);s.insert(1);set<int>::iterator it = s.begin();while (it != s.end()){cout << *it << " ";++it;}cout << endl;for (auto e : s){cout << e << " ";}cout << endl;
}int main()
{test01();return 0;
}

对于 insert 的使用我们已经轻车熟路了。
在这里插入图片描述
我们发现结果跟插入的数据好像不匹配,这是因为set底层是平衡二叉树,自带排序属性,而且遇到重复的值不会再次插入,所以 set具有 排序 + 去重 的功能。
在这里插入图片描述

#include<iostream>
#include<set>
using namespace std;void test03()
{set<int> s;s.insert(5);s.insert(2);s.insert(4);s.insert(1);s.insert(3);s.insert(2);s.insert(1);set<int>::iterator it = s.find(5);// 使用迭代器进行删除时必须保证迭代器有效s.erase(it);// 使用指定value进行删除,如果该值存在则删除,不存在不做任何处理s.erase(666);for (auto e : s){cout << e << " ";}cout << endl;
}int main()
{test03();return 0;
}

在这里插入图片描述

当使用迭代器进行删除时确保迭代器有效,否则会报错。

在这里插入图片描述

#include<iostream>
#include<set>
using namespace std;void test02()
{set<int> s;s.insert(5);s.insert(2);s.insert(4);s.insert(1);s.insert(3);s.insert(2);s.insert(1);set<int>::iterator it = s.find(5);if (it != s.end()){cout << "找到了" << endl;}
}int main()
{test02();return 0;
}

find查找到元素会返回一个指向元素的迭代器,没找到则返回指向end()的迭代器。
在这里插入图片描述

在这里插入图片描述
count()会返回这个值有几个。

#include<iostream>
#include<set>
using namespace std;void test04()
{set<int> s;s.insert(5);s.insert(2);s.insert(4);s.insert(1);s.insert(3);s.insert(2);s.insert(1);cout << s.count(1) << endl;cout << s.count(77) << endl;
}int main()
{test04();return 0;
}

在这里插入图片描述

在这里插入图片描述

#include<iostream>
#include<set>
using namespace std;void test05()
{set<int> s;s.insert(5);s.insert(2);s.insert(4);s.insert(1);s.insert(6);s.insert(2);s.insert(1);// lower_bound返回 容器里第一个 >= value的值auto start = s.lower_bound(3);// opper_bound返回 容器里第一个 > value的值auto finish = s.upper_bound(5);cout << *start << endl;cout << *finish << endl;// 迭代器区间删除s.erase(start, finish);for (auto e : s){cout << e << " ";}cout << endl;
}int main()
{test05();return 0;
}

lower_bound返回 容器里第一个 >= value的值
opper_bound返回 容器里第一个 > value的值
在这里插入图片描述

4. multiset

multiset的用法与set基本一样,只是 multiset允许出现重复值
在这里插入图片描述
此时这里的返回值就有了意义,返回删除的元素个数。

在这里插入图片描述
当有重复值时,find返回的迭代器指向中序遍历的第一个要查找的值。

5. map的介绍

map文档
在这里插入图片描述
map底层其实是 pair 。而 pair 其实是一个类模板。
在这里插入图片描述

成员变量有两个,一个first,一个second,在map里,first一般存的是key,second存的是value
在这里插入图片描述

6. map的使用

使用map时记得包含 map 头文件哦。
在这里插入图片描述

#include<iostream>
#include<map>
using namespace std;void test01()
{map<string, string> dict;dict.insert(pair<string, string>("sort", "排序"));dict.insert(pair<string, string>("string", "字符串"));dict.insert({ "apple", "苹果" });dict.insert(make_pair("sort", "排序"));map<string, string>::iterator it = dict.begin();while (it != dict.end()){// 两种获取key和value的方法cout << (*it).first << " " << it->second << endl;++it;}
}int main()
{test01();return 0;
}

make_pair是一个模板函数,跟pair那种写法没区别。
在这里插入图片描述
在这里插入图片描述
map同样具有 排序 + 去重 的功能,排序的依据是map的 key

#include<iostream>
#include<map>
using namespace std;void test02()
{map<string, string> dict;dict.insert(make_pair("sort", "排序"));dict.insert(make_pair("string", "字符串"));dict.insert(make_pair("sort", "xxxx"));for (auto& e : dict){cout << e.first << " " << e.second << endl;}
}int main()
{test02();return 0;
}

此时第三个插入并不会插入,也不会更新。
在这里插入图片描述
map的其他成员函数基本没啥大的变化,我们不再赘述。

7. multimap

multimap跟map的区别与multiset与set的区别类似。
在这里插入图片描述

#include<iostream>
#include<map>
using namespace std;void test03()
{multimap<string, string> dict;dict.insert(make_pair("sort", "排序"));dict.insert(make_pair("string", "字符串"));dict.insert(make_pair("sort", "xxxx"));dict.insert(make_pair("sort", "排序"));for (auto& e : dict){cout << e.first << " " << e.second << endl;}
}int main()
{test03();return 0;
}

在这里插入图片描述
此时就可以插入重复值了。(排序时只看key)

8. map中重载的operator[]

map的普通统计次数:

#include<iostream>
#include<map>
using namespace std;void test04()
{string arr[] = { "苹果","西瓜","苹果","西瓜","苹果","苹果","西瓜","苹果","香蕉","苹果","西瓜","香蕉","草莓" };map<string, int> countMap;for (auto& e : arr){// 查找map<string, int>::iterator it = countMap.find(e);// 有则数量+1if (it != countMap.end()){it->second++;}// 没有则插入else{countMap.insert(make_pair(e, 1));}}for (auto& e : countMap){cout << e.first << " " << e.second << endl;}
}int main()
{test04();return 0;
}

在这里插入图片描述
在这里插入图片描述
当key存在时,operator[]可以返回这个key所映射的value的引用。
operator[]的访问原型:
在这里插入图片描述
在这里插入图片描述
map的insert函数返回一个pair,第二个数据代表是否插入成功,如果成功(第一次出现)则返回 true 。第一个数据代表指向这个key的迭代器(已经存在的或新插入的)。
所以上面的统计次数代码可以改成:

#include<iostream>
#include<map>
using namespace std;void test05()
{string arr[] = { "苹果","西瓜","苹果","西瓜","苹果","苹果","西瓜","苹果","香蕉","苹果","西瓜","香蕉","草莓" };map<string, int> countMap;for (auto& e : arr){pair<map<string, int>::iterator, bool> ret;ret = countMap.insert(make_pair(e, 1));// 已经存在if (ret.second == false){// 迭代器指向的value + 1ret.first->second++;}}for (auto& e : countMap){cout << e.first << " " << e.second << endl;}
}int main()
{test05();return 0;
}

在这里插入图片描述

所以operator[]的访问就跟insert差不多,插入的value是类型的默认构造值。所以上面的统计代码也可以写成:

#include<iostream>
#include<map>
using namespace std;void test06()
{string arr[] = { "苹果","西瓜","苹果","西瓜","苹果","苹果","西瓜","苹果","香蕉","苹果","西瓜","香蕉","草莓" };map<string, int> countMap;for (auto& e : arr){countMap[e]++;}for (auto& e : countMap){cout << e.first << " " << e.second << endl;}
}int main()
{test06();return 0;
}

在这里插入图片描述

于是,插入也可以写成这样:

void test07()
{map<string, string> dict;// 插入dict["sort"];// 查找cout << dict["sort"] << endl;// 修改dict["sort"] = "xxx";// 插入 + 修改dict["apple"] = "苹果";
}

未完待续

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

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

相关文章

抖音小店什么产品最好卖?六月份的必爆产品!商家抓紧上架!

哈喽~我是电商月月 做抖音小店&#xff0c;爆款是非常吃香的&#xff0c;但普通玩家只有在爆款出来的那几天才能发现&#xff0c;再去截流&#xff0c;其实热度已经不高了&#xff0c;那想吃到这一口“螃蟹”只能自己去挖掘 每年爆的产品就是那几种&#xff0c;我们可以朝这几…

HackTheBox-Machines--Bank

文章目录 0x01 信息收集0x02 文件上传漏洞利用0x03 权限提升方法一&#xff1a;SUID提权方法二&#xff1a;配置不当提权 Bank 测试过程 0x01 信息收集 1.端口扫描 发现 ssh(22)、DNS(53)、HTTP(80) 端口 nmap -sC -sV 10.129.29.200访问 80 端口&#xff0c;页面为Apache2 U…

非授权人员进入报警系统

非授权人员进入报警系统基于智能视频分析技术和深度学习技术&#xff0c;非授权人员进入报警系统通过现场已经装好的监控摄像头针对人体进行精准检测&#xff0c;并根据设置的禁入区范围进行判断。通过图像处理和人体识别算法&#xff0c;非授权人员进入报警系统可以在实时监测…

鸿蒙HarmonyOS开发中的易混点归纳-持续补充中

相关文章目录 鸿蒙HarmonyOS开发术语全解&#xff1a;小白也能看懂&#xff01; 文章目录 相关文章目录前言一、build()函数和Builder装饰器&#xff1f;二、自定义组件和系统组件&#xff08;内置组件&#xff09;三、组件和页面四、自定义弹窗和其他弹窗总结 前言 一、build…

一个通过ADC采集NTC热敏电阻的温度传感器

前言: 如何设计一个电路,使用具有逐次逼近寄存器(SAR)模数转换器(ADC)的热敏电阻直接监测温度呢?温度传感电路需要使用负温度系数(NTC)热敏电阻与电阻器串联形成分压器,监测-25C至100C的温度范围。分压器具有产生与监测的温度成反比的输出电压的效果。电阻器分压器的…

Flink 高可用之StandAlone-HA模式(一)

obManager存在单点故障&#xff08;SPOF&#xff1a;Single Point Of Failure&#xff09;&#xff0c;因此对Flink做HA&#xff0c;主要是对JobManager做HA&#xff0c;根据Flink集群的部署模式不同&#xff0c;分为Standalone、OnYarn&#xff0c;本文主要涉及Standalone模式…

R语言数据分析案例-巴西固体燃料排放量预测与分析

1 背景 自18世纪中叶以来&#xff0c;由于快速城市化、人口增长和技术发展&#xff0c;导致一氧化二氮&#xff08;N2O&#xff09;、 甲烷&#xff08;CH4&#xff09;和二氧化碳&#xff08;CO 2&#xff09;等温室气体浓度急剧上升&#xff0c;引发了全球变暖、海平面上 升…

别说废话!说话说到点上,项目高效沟通的底层逻辑揭秘

假设你下周要在领导和同事面前汇报项目进度&#xff0c;你会怎么做&#xff1f;很多人可能会去网上搜一个项目介绍模板&#xff0c;然后按照模板来填充内容。最后&#xff0c;汇报幻灯片做了 80 页&#xff0c;自己觉得非常充实&#xff0c;但是却被领导痛批了一顿。 这样的境…

景源畅信电商:抖店怎么提高店铺的权重?

在竞争激烈的电商市场&#xff0c;如何提升抖店店铺权重成为商家关注的焦点。店铺权重是决定商品搜索排名的关键因素之一&#xff0c;直接关系到店铺流量和销量。提高店铺权重并非一蹴而就&#xff0c;而是一个系统工程&#xff0c;需要从多个维度着手优化。 一、优化商品标题和…

(二)vForm 动态表单设计器之下拉、选择

系列文章目录 &#xff08;一&#xff09;vForm 动态表单设计器之使用 目录 系列文章目录 前言 一、后端需提供接口 二、组件配置 总结 前言 动态表单下拉、选择等组件&#xff0c;大概率要使用数据库中的数据&#xff0c;那么vForm如何拿到数据库中的数据呢&#xff1f;跟随…

Java ( 框架界面 , 按钮 , 动作监听ActionListener ,鼠标监听MouseListener,键盘监听KeyListener)的使用方法

package 拼图阶段任务.ui;import javax.swing.*; import java.awt.*; import java.awt.event.*;public class UseMethod {public static void main(String[] args) { // 框架的用法JFrame jf new JFrame();// 设置界面的宽高jf.setSize(603,680);// 设置界面的标题jf.setTitle…

Linux: network: send 失败的时候要不要close socket?

最近遇到一个例子&#xff0c;说有zerowindow出现&#xff1b;出现的原因是接收方的CPU被其他程序吃光&#xff0c;导致socket的read函数处理非常慢。说明接收端的接收缓存不够用。发送端自然而然的要停止发送。 但是如果在接收方的recv buff&#xff0c;以及发送方的send buf…

智能车竞赛指南:从零到一,驶向自动驾驶的未来

智能车竞赛指南&#xff1a;从零到一&#xff0c;驶向自动驾驶的未来 一、智能车竞赛概览1.1 竞赛介绍1.2 竞赛分类 二、智能车开发技术基础2.1 硬件平台2.2 软件开发 三、实战案例&#xff1a;循线小车开发3.1 系统架构3.2 代码示例 四、技术项目&#xff1a;基于ROS的视觉导航…

PersonalLLM——探索LLM是否能根据五大人格特质重新塑造一个新的角色?

1.概述 近年来&#xff0c;大型语言模型&#xff08;LLMs&#xff09;&#xff0c;例如ChatGPT&#xff0c;致力于构建能够辅助人类的个性化人工智能代理&#xff0c;这些代理以进行类似人类的对话为重点。在学术领域&#xff0c;尤其是社会科学中&#xff0c;一些研究报告已经…

Nacos 进阶篇---Nacos服务端怎么维护不健康的微服务实例 ?(七)

一、引言 在 Nacos 后台管理服务列表中&#xff0c;我们可以看到微服务列表&#xff0c;其中有一栏叫“健康实例数” &#xff08;如下图&#xff09;&#xff0c;表示对应的客户端实例信息是否可用状态。 那Nacos服务端是怎么感知客户端的状态是否可用呢 &#xff1f; 本章…

JAVA 中 HTTP 基本认证(Basic Authentication)

目录 服务端这么做服务端告知客户端使用 Basic Authentication 方式进行认证服务端接收并处理客户端按照 Basic Authentication 方式发送的数据 客户端这么做如果客户端是浏览器如果客户端是 RestTemplat如果客户端是 HttpClient 其它参考 服务端这么做 服务端告知客户端使用 …

Unity数据持久化2——XML

简介&#xff1a; 基础知识 XML文件格式 XML基本语法 XML属性 练习&#xff1a; C#读取存储XML XML文件存放位置 读取XML文件 练习&#xff1a; 存储修改XML文件 练习&#xff1a; 总结 实践小项目 必备知识点 必备知识点——C#中XML序列化 必备知识点——C#中XML反序列化 必备…

5.23-

回顾 I0多路复用的原理? 程序首先向操作系统发起一个IO多路复用请求&#xff0c;告诉操作系统需要监视哪些IO通道。这些IO通道可以包括网络套接字、文件描述符等操作系统随后会将这些IO通道放入一个队列中&#xff0c;并在某个IO通道就绪时&#xff08;如数据到达、文件可读…

Servlet的request对象

request对象的继承关系 1.HttpServletRequest接口继承了ServletRequest接口&#xff0c;对其父接口进行了扩展&#xff0c;可以处理满足所有http协议的请求 2.HttpServletRequest和ServletRequest都是接口&#xff0c;不能创建对象&#xff0c;因此在tomcat底层定义实现类并创…

Mysql总结1

Mysql常见日志 &#xff08;1&#xff09;错误日志&#xff1a;记录数据库服务器启动、停止、运行时存在的问题&#xff1b; &#xff08;2&#xff09;慢查询日志&#xff1a;记录查询时间超过long_query_time的sql语句&#xff0c;其中long_query_time可配置&#xff0c;且…