【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.mzph.cn/pingmian/13718.shtml

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

相关文章

Golang | Leetcode Golang题解之第99题恢复二叉搜索树

题目&#xff1a; 题解&#xff1a; func recoverTree(root *TreeNode) {var x, y, pred, predecessor *TreeNodefor root ! nil {if root.Left ! nil {// predecessor 节点就是当前 root 节点向左走一步&#xff0c;然后一直向右走至无法走为止predecessor root.Leftfor pr…

OpenHarmony开发之MQTT讲解

相信MQTT这个名称大家都不陌生&#xff0c;物联网的开发必然会遇到MQTT相关知识的应用。那么什么是MQTT&#xff1f;它有什么特点&#xff1f;它能解决什么问题&#xff1f;它是如何工作的&#xff1f;OpenAtom OpenHarmony&#xff08;以下简称“OpenHarmony”&#xff09;的物…

简单快捷的图片格式转换工具:认识webp2jpg-online

经常写博客或记笔记的朋友们可能会碰到图床不支持的图片格式或图片太大需要压缩的情况。通常&#xff0c;我们会在浏览器中搜索在线图片格式转换器&#xff0c;但这些转换器往往伴有烦人的广告或要求登录&#xff0c;并且支持的转换格式有限。最近&#xff0c;我在浏览 GitHub …

hls.js实现分片播放视频

前言&#xff1a;hls.js官网&#xff1a;hls.js - npm 一、demo——在HTML中使用 <audio id"audio" controls></audio><script src"https://cdn.jsdelivr.net/npm/hls.jslatest"></script> <script>document.addEventList…

upload-labs 通关方法

目录 Less-1&#xff08;JS前端验证&#xff09; Less-2&#xff08;MIME验证&#xff09; Less-3&#xff08;黑名单&#xff0c;特殊过滤&#xff09; Less-4&#xff08;黑名单验证&#xff0c;.htaccess&#xff09; Less-5&#xff08;黑名单&#xff0c;点空格点绕过…

Qt | QCalendarWidget 类(日历)

01、QCalendarWidget 类 1、QCalendarWidget 类是 QWidget 的直接子类,该类用于日历,见下图 02、QCalendarWidget 属性 ①、dateEditAcceptDelay:int 访问函数:int dateEditAcceptDelay()const; void setDateEditAcceptDelay(int) 获取和设置日期编辑器的延迟时间(以毫秒…

给树莓派配置静态IP地址

第一步&#xff1a;查找默认网关 打开windowr&#xff1b;输入cmd&#xff0c; 输入 最后一行就是默认网关 ipconfig第二步&#xff1a;确定分配好给树莓派的IP地址 要注意&#xff1a;&#xff08;1&#xff09;静态ip地址与路由器网段保持一致&#xff08;2&#xff09;与…

压缩设备液压控制比例放大器

液压比例阀放大器是液压控制系统中的重要部件之一&#xff0c;用于控制输出油压方向流量和压力的精确控制。它由BEUEC比例放大器和比例电磁阀组成&#xff0c;通过调节比例放大器的增益和灵敏度参数&#xff0c;可以实现对液压系统输出油压方向流量和压力的精确控制。适用于各种…

动态IP与静态IP有什么区别?如何选择?

动态IP和静态IP都是指网络设备&#xff08;如计算机、服务器、路由器等&#xff09;在互联网上分配的IP地址的类型。 一、什么是动态IP&#xff0c;什么是静态IP&#xff1f; 1、什么是动态IP&#xff1f; 动态IP是指由Internet服务提供商&#xff08;ISP&#xff09;动态分配…

SpringBoot中使用AOP实现日志记录功能

目录 一、SpringBoot框架介绍 二、什么是 AOP 三、日志记录的必要性 四、SpringBoot中如何使用AOP实现日志记录功能 一、SpringBoot框架介绍 SpringBoot是一个开源的Java开发框架&#xff0c;旨在简化基于Spring框架的应用程序的开发。它提供了一套开箱即用的工具&#xf…

express.js--连接数据库,并且增删改查(四)

使用数据库需要在电脑安装mysql&#xff0c;然后使用navicat 我没有下载mysql,我使用的是小皮里面的数据库&#xff0c;需要破解版的navicat可以私信我 安装mysql npm i mysql 数据库的基本信息&#xff0c;我是直接写到配置文件里面的 config/index.js module.exports {…

【Android】联系人列表补充

真布局--叠起来垂直管 效果展示 部分代码&#xff08;在activity_main&#xff09;里面 <FrameLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"…

如何在Windows下使用Docker Desktop运行CentOS容器

引言&#xff1a; 在Windows操作系统中&#xff0c;我们可以使用Docker Desktop来轻松运行和管理各种Linux容器&#xff0c;包括CentOS。今天&#xff0c;我们就来详细讲解一下如何在Windows环境下使用Docker Desktop来运行CentOS容器。 一、安装Docker Desktop 首先&#x…

WPF中CommandParameter用法

1. 界面样式 2. XAML中代码部分 <ButtonGrid.Row"0"Grid.Column"1"Command"{Binding BtnClick_Number}"CommandParameter"7"Content"7"Style"{StaticResource BtnStyle_Num}" /> <ButtonGrid.Row"…

【个人商业画布】你有思考过把自己当成一家公司来经营吗?

商业模式画布(Business Model Canvas)&#xff0c;是亚历山大奥斯特瓦德在《商业模式新生代》中提出的一种用于描述商业模式、可视化商业模式、评估商业模式以及改变商业模式的通用语言。它由9个模块构成&#xff0c;帮助创业者理清为“细分客户提供独有价值”&#xff0c;从而…

浅谈OpenHarmony LiteOS-A内核之基础硬件——中断控制器GIC400

一、前言 OpenAtom OpenHarmony&#xff08;以下简称“OpenHarmony”&#xff09;采用多内核架构&#xff0c;支持Linux内核的标准系统、LiteOS-A的小型系统、LiteOS-M的轻量系统。 其中LiteOS-A要求设备具备一定的处理能力&#xff0c;对比LiteOS-M&#xff0c;LiteOS-A支持…

国赛部分复现

MISC 神秘文件 下载解压后是个pptm文件&#xff0c;内容丰富 使用010打开ppt查看 发现为PK开头&#xff0c;属于压缩包文件。复制粘贴ppt&#xff0c;修改副本后缀为.zip并解压 part1 查看属性&#xff0c;发现奇怪字符 QFCfpPQ6ZymuM3gq 根据提示Bifid chipher&#xff0c;…

【Linux】Linux信号产生,接受与处理机制

理解Linux信号产生&#xff0c;接受与处理机制 信号是Linux操作系统中一种用于进程间通信和异步事件处理的机制。在本文中&#xff0c;我们将结合Linux的源码&#xff0c;深入分析信号的产生、发送、接收和处理的底层原理。 文章目录 理解Linux信号产生&#xff0c;接受与处理…

Android 几个简单的自定义对话框介绍

Android 几个简单的自定义对话框介绍 文章目录 一、前言二、对话框相关内容1、效果2、对话框显示的调用代码&#xff08;1&#xff09;原生对话框代码&#xff1a;&#xff08;2&#xff09;自定义对话框代码&#xff1a; 3、对话框SweetAlertDialog 主要实现代码&#xff1a;4…

【Linux】-Elasticsearch安装部署[16]

目录 简介 安装 1、添加yum仓库 2、安装es 3、配置es 4、启动es 5、关闭防火墙 6、测试 简介 全文搜索属于最常见的要求&#xff0c;开源的Elasticsearch&#xff08;以下简称es&#xff09;是目前全文搜索引擎的首选。它可以快速的储存、搜索和分析海量数据。维基百科…