【C++】- set和map的具体使用(multiset和multimap的介绍)

news2025/1/23 3:59:35

在这里插入图片描述
💖作者:小树苗渴望变成参天大树🎈
🎉作者宣言:认真写好每一篇博客💤
🎊作者gitee:gitee✨
💞作者专栏:C语言,数据结构初阶,Linux,C++ 动态规划算法🎄
如 果 你 喜 欢 作 者 的 文 章 ,就 给 作 者 点 点 关 注 吧!

文章目录

  • 前言
  • 一、set
  • 二、set的接口以及使用方法
    • 2.1构造函数
    • 2.2迭代器
    • 2.3修改函数接口
    • 2.4操作函数
  • 三、map
    • 3.1插入和删除函数
    • 3.2operator[]函数
  • 四、set和map的应用
    • 4.1[349. 两个数组的交集](https://leetcode.cn/problems/intersection-of-two-arrays/description/)
    • 4.2[有效的括号](https://leetcode.cn/problems/valid-parentheses/description/)


前言

今天我们开始讲解进阶中的STL,这个容器相比较前面而言结构更加的复杂,但是用处也是更加的多,大家还记得我进阶的上一篇博客写的是什么吗??是二叉搜索树,所以今天这篇讲的STL就和上一篇博客讲的结构有关系,大家最好先提前看看二叉搜索树的博客,才能理解一些接口为什么会出现这样的效果,话不多说,我们开始介绍两个STL的容器-----set和map


在初阶阶段,我们已经接触过STL中的部分容器,比如:vector、list、deque、
forward_list(C++11)等,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身。那什么是关联式容器?它与序列式容器有什么区别?

关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是<key, value>结构的键值对,在数据检索时比序列式容器效率更高

键值对
用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息。比如:现在要建立一个英汉互译的字典,那该字典中必然有英文单词与其对应的中文含义,而且,英文单词与其中文含义是一一对应的关系,即通过该应该单词,在词典中就可以找到与其对应的中文含义

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)
	{}
};

根据应用场景的不桶,STL总共实现了两种不同结构的管理式容器:树型结构与哈希结构。树型结构的关联式容器主要有四种:map、set、multimap、multiset。这四种容器的共同点是:使用平衡搜索树(即红黑树)作为其底层结果,容器中的元素是一个有序的序列。下面一依次介绍每一个容器。

注意:set就是key的模型,map就是key_value的模型

一、set

注意:

  1. 与map/multimap不同,map/multimap中存储的是真正的键值对<key, value>,set中只放value,但在底层实际存放的是由<value, value>构成的键值对。
  2. set中插入元素时,只需要插入value即可,不需要构造键值对。
  3. set中的元素不可以重复(因此可以使用set进行去重)。
  4. 使用set的迭代器遍历set中的元素,可以得到有序序列
  5. set中的元素默认按照小于来比较
  6. set中查找某个元素,时间复杂度为: l o g 2 n log_2 n log2n
  7. set中的元素不允许修改(为什么?)一会后面会说到
  8. set中的底层使用二叉搜索树(红黑树)来实现

我们一起来看看set在文档的中的具体介绍吧
在这里插入图片描述
T: set中存放元素的类型,实际在底层存储<value, value>的键值对。
Compare:set中元素默认按照小于来比较
Alloc:set中元素空间的管理方式,使用STL提供的空间配置器管理

我们看看提供了一个仿函数,原因是set在插入的时候需要进行内部的比较,每个类的比较的比较方式不一样,所以需要提供仿函数,来实现我们自己的比较逻辑。set的模板参数还是比较好理解,接下来我就带大家来看看set有哪些接口,具体是怎么使用吧.

二、set的接口以及使用方法

2.1构造函数

我们只需要研究构造函数,赋值和析构可以不用了解,都是和之前的一样的
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这就是我们三种构造函数,通过监视窗口我们有没有发现一些细节的问题,我们看到v里面原本乱序的数据在s2中就编程有序了,而且原来有重复数据,而s2里面叶没有重复数据了,所以这是set一个比较需要了解的知识点,原因是set底层是类似于二叉搜索数的实现原理,才会变成有序的,但set里面有相同数据,就不允许插入了,在二叉搜索数的时候就已经知道怎么做了,这是set,也是map的特性----去重和排序

2.2迭代器

在这里插入图片描述
迭代器这部分没有什么好讲解的,迭代器设计初衷,就是为了是所有容器的遍历都是一样的,博主就带大家过一遍这个迭代器的使用
在这里插入图片描述
我们看到排序了又去重了,我们看看修改数据会发生什么??
在这里插入图片描述

我们看到不允许进行修改,原因是修改会破坏二叉搜索树的结构,如果想要修改一个数据可以先删除,在插入想要修改后的数据。

为什么不可以进行修改呢,是怎么控制的?
在这里插入图片描述

我们发现他的迭代器都是使用const修饰的,所以可以控制数据不会被修改,其他的迭代器都是和之前一眼固定用法,我也不做过多的演示了,大家感兴趣自己下去实验一下。

2.3修改函数接口

在这里插入图片描述
插入函数insert:
在这里插入图片描述
这个pair一会将set的最后一个函数的时候在细讲!!

	set<int> s;
	s.insert(4);
	s.insert(3);
	s.insert(6);
	s.insert(2);
	s.insert(3);
	set<int>::iterator it = s.begin();
	for (auto e : s)
	{
		cout << *it << " ";
		it++;
	}

在这里插入图片描述
这和我们构造函数看到的效果是一样的。

删除函数erase:
在这里插入图片描述

	cout << endl;
	s.erase(1);
	s.erase(2);
	s.erase(3);
	it = s.begin();
	for (auto e : s)
	{
		cout << *it << " ";
		it++;
	}

在这里插入图片描述
这个删除的效果就很简单,有就删除,没有就不做任何处理

后面几个就不做介绍,clear和swap大家肯定都会,最后两个等到C++11章节在细说

2.4操作函数

在这里插入图片描述

这两个在set里面含义是一样,都是获取key的值,在map里面就不一样

在这里插入图片描述

这三个函数大家最熟只不过了,也不做演示了。

在这里插入图片描述

这几个函数我要做一下特别介绍,因为这才是set和其他STL容器的不同.


find:
在这里插入图片描述

找到了就返回迭代器位置,没找到就返回end的位置,左闭右开,所以是最后一个元素后面的一个位置

具体使用:
在这里插入图片描述

我们看到set自带的和库里面的查找函数都可以完成查找的功能,为什么set还要单独在设计一个查找函数的,原因是,set的查找函数的左右找,不是像库里面的一个个的遍历查找,所以自带的复杂度可以达到O(logn),而库里面的只有O(n)。


count:
在这里插入图片描述
这个函数对于set其他意义不大,他是统计数据出现的次数,而set里面的数据没有重复的,所以只有1个,在set中这个函数可以判断一个数据在不在
在这里插入图片描述
那这个函数的意义在哪呢,我们讲完剩下来的三个函数在具体说。


lower_bound和upper_bound:
在这里插入图片描述
正常情况这两个函数是同时使用的,一个用来找左边界,一个用来找右边界
在这里插入图片描述

lower_bound是找到大于等于val值的迭代器
upper_bound是找到大于val值的迭代器

原因是他要配合插入删除来使用,因为插入和删除都可以使用迭代器来操作,而且是左闭右开的,所以upper_bound是返回比val大的迭代器位置返回。


equal_range:
在这里插入图片描述

在这里插入图片描述

pair其实是一个类模板结构,这个类里面右两个变量,把两个值放在一个结构里面了,一会再讲map的时候会讲为什么会这样设计。

具体使用:
在这里插入图片描述

我们返回的是返回的是一个pair的结构,所以第一个数是返回的是val的迭代器,而第二个返回的是最后依次出现val值后一位值的迭代器,再set当中体现不出来


multiset:
上面的count和equal_range其实是为multiset设计的,这个STL有什么功能呢,相比较于set这个函数不去重

在这里插入图片描述

通过上面的图我们发现count可以统计val出现了几次,equal_range的first返回第一次val出现的迭代器,second返回最后一个val出现的下一个位置,其实是为了插入和删除的,这个大家要明白.

注意: multiset的其他使用和set是一样的,我们大部分情况都是使用set这个容器,其次set的主要功能是判断在不在。

三、map

在这里插入图片描述
学习了set我们再学习map其实难度会好很多,我们的map是一个key_value模型,两者是绑定的。我们的map和set一样可以去重,他的key只能由一个,但是value不是唯一。

接下来就带大家看看由哪些接口函数吧
在这里插入图片描述

接下来博主会介绍圈主的部分,五个操作函数的使用和set是一样的,传key的值就可以了,这个大家下来看看文档就可以理解了

3.1插入和删除函数

之前再set插入的时候返回值就是pair,为什么要设计程这样,我们知道,key_value模型,是讲着两个值进行绑定在一起,所以再插入或者删除的是都是一起操作的,既然这样,我们把这两个值放到一个结构体里面,通过控制这个结构体来控制这两个值,所以pair就是相当于这样的一个作用,我们来看一下插入函数

insert:
在这里插入图片描述
我们插入的时候也是插入一个结构体对象的引用,我们来具体来看看怎么使用:

	map<int, string> m1;
	pair<int, string> p(1, "数字1");//最基本的插入方式
	m1.insert(p);

	m1.insert(make_pair(2, "数字2"));//make_pair调用pair

	m1.insert({ 3, "数字3" });//c++11的多参数隐式类型转换
	m1.insert({ 3, "数字3" });//c++11的多参数隐式类型转换
	m1.insert({ 3, "数字3" });//c++11的多参数隐式类型转换
	
	m1.insert({ 4, "数字3" });//c++11的多参数隐式类型转换

在这里插入图片描述
在这里插入图片描述
我们看到map也实现了去重,当key有相同的就不插入,不覆盖,插入过程值比较key,value相同无所谓,make_pair也是我们平时使用最多的,而且也不能对插入后的key进行修改


其次我们看到插入也会返回一个pair,一个是插入位置的迭代器,一个是插入是否成功。
在这里插入图片描述
这个大家一定要先理解,因为一会讲解的[]就和这个有关,先给大家铺垫一个比较好理解的,才能更好的接受不太好理解的

erase:
在这里插入图片描述

只需要传key的值就可以了。博主就不做具体演示了。

3.2operator[]函数

接下来带大家来看看之前的题目,大家还记得统计水果次数的功能吗??大家可以看看之前写的二叉搜索树,今天我们有map就很简单我们来看看代码:

	//第一种
	map<string, int> countMap;
	string arr[] = { "苹果","香蕉","苹果","梨子","苹果","香蕉","梨子" };
	for (auto e : arr)
	{
		auto it = countMap.find(e);
		if (it == countMap.end())
		{
			countMap.insert(make_pair(e, 1));
		}
		else
		{
			it->second++;
		}
	}
	map<string, int>::iterator it = countMap.begin();
	for (auto e : countMap)
	{
		cout << it->first << " " << it->second << endl;
		it++;
	}
	
	//第二种
	cout << endl;
	map<string, int> countMap1;
	string arr1[] = { "苹果","香蕉","苹果","梨子","苹果","香蕉","梨子" };
	for (auto e : arr1)
	{
		countMap1[e]++;
	}
	map<string, int>::iterator it1 = countMap1.begin();
	for (auto e : countMap1)
	{
		cout << it1->first << " " << it1->second << endl;
		it1++;
	}

在这里插入图片描述
通过第一种的思路,我们第二种看着很简单,但是里面的核心思路还是和第一种一样,内部是插入操作,我们来通过文档看看这个[]实现的原理是什么??

我们来看文档:
在这里插入图片描述

大家还记得我们插入操作的时候研究insert返回值的的案例吗。和这个一模一样。
在这里插入图片描述
此时大家应该明白[]的工作原理了吧,其实就要搞懂调用关系以及pair的特性,这个再模拟实现的时候会更清楚的,大家先理解着。


接下来就是multimap这个容器,他这个容器和map几乎一模一样,他不可以去重,所以[]这个函数他就没有,其余的使用和毛一样,博主就不做具体介绍了,接下来博主来使用set和map带啊大家来解决原来比较难解决的题目

注意:map是用来统计次数的,也可以判断数据在不在的,map的使用度更广泛

四、set和map的应用

4.1349. 两个数组的交集

这个题目也是很经典的,接下来我讲带大家怎么来解决这个问题。
在这里插入图片描述
所以这题我们不需要统计次数,所以使用set就可以了,set可以去重也可以排序,所以符合上图的分析思路,来看代码:

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        vector<int>v;
        set<int> s1(nums1.begin(),nums1.end());
        set<int> s2(nums2.begin(),nums2.end());
        
        auto it1=s1.begin();
        auto it2=s2.begin();
        while(it1!=s1.end()&&it2!=s2.end())
        {
            if(*it1<*it2)
            {
                it1++;
            }
            else if(*it1>*it2)
            {
                it2++;
            }
            else
            {
                v.push_back(*it1);
                it1++;
                it2++;
            }
        }
        return v;
    }
};

4.2有效的括号

这个题目大家非常熟悉不过了,因为需要把括号两边进行绑定,所以需要使用map去操作,这样题目说有更多的括号都不用担心,再前面进行修改就好了。

class Solution {
public:
    bool isValid(string s) {
    stack<char> st;
    map<char,char> m;
    m['(']=')';
    m['{']='}';
    m['[']=']';
    for(auto e:s)
    {
        if(m.count(e))
        {
            st.push(e);
        }
        else
        {
            if(st.empty())
            {
                return false;
            }
            else
            {
                char top=st.top();
                st.pop();
                if(m[top]!=e)
                {
                   return false;
                }
            }
        }
    }
         return st.empty();
    }
};

通过上面两个应用大家对set和map应该了解了。接下来我将给大家讲解AVL树了,难度有所提升,希望大家可以好好理解,加深理解,今天讲的对后面的模拟实现会很有帮助的,我们下篇再见

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

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

相关文章

error:Failed building wheel for XXX

解决方案适用于大多数的pip 安装时出现的Failed building wheel for XXX 出现问题 按以往快速安装包的经验&#xff0c;第一反应当然是使用简单又快捷的terminal命令加上镜像&#xff0c;如下&#xff1a; pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple结…

群晖Cloud Sync数据同步到百度云、另一台群晖、nextcloud教程

群晖Cloud Sync数据同步到百度云、另一台群晖、nextcloud教程 一、群晖套件中下载Cloud Sync 二、同步到百度云盘 打开Cloud Sync&#xff0c;点击左上角的号&#xff0c;云供应商选择百度云。 这里可以选择双向备份&#xff0c;也可以只上穿到百度云的仅上传本地更改。因为百…

D盘无法格式化?3个方法!轻松解决问题!

“我的电脑d盘好像中病毒了&#xff0c;我想将它格式化但是每次操作都显示d盘无法格式化。这是为什么呢&#xff1f;我应该怎么解决&#xff1f;” 有时候&#xff0c;我们的电脑可能会出现一些问题&#xff0c;导致我们不得不将某些磁盘进行格式化操作。这时候问题就出现了。有…

CSP 202005-1 重复局面

题目背景 国际象棋在对局时&#xff0c;同一局面连续或间断出现3次或3次以上&#xff0c;可由任意一方提出和棋。 问题描述 国际象棋每一个局面可以用大小为 的字符数组来表示&#xff0c;其中每一位对应棋盘上的一个格子。六种棋子王、后、车、象、马、兵分别用字母 k、q、…

Polarion导入需求(Word)

简介 将需求文档导入Polarion并实现自动创建工作项具有多个优势&#xff0c;这些优势有助于提高项目管理和协作的效率&#xff0c;以下是一些主要的优势点&#xff1a;减少手动工作&#xff1a; 自动创建工作项可以显著减少手动数据输入的工作量。不再需要手动逐一创建每个工作…

聚类-kmeans

聚类算法是无监督学习算法&#xff0c;指定将数据分成k个簇。然后通过每个点到各个簇的中心的欧氏距离来分类。 kmeans本身会陷入局部最小值的状况&#xff0c;二分kmeans可以解决这一点。 二分kmeans是遍历所有的簇&#xff0c;将其分成2个&#xff0c;比较哪一个分裂结果更…

2023年7月京东休闲食品行业品牌销售排行榜(京东大数据)

鲸参谋监测的京东平台7月份休闲食品市场销售数据已出炉&#xff01; 根据鲸参谋平台的数据显示&#xff0c;7月份休闲食品市场整体呈现下滑趋势。当月休闲食品在京东平台的销量为3400万&#xff0c;环比下降约26%&#xff0c;同比下降约26%&#xff1b;销售额将近11亿&#xf…

Equall Apple 的革命性变压器:一个宽幅前馈,实现前所未有的效率和精度

变压器架构已显示出显著的可扩展性&#xff0c;从而大大提高了精度。然而&#xff0c;这种进步是以极高的计算要求为代价的&#xff0c;这已成为实际应用中的重大障碍。 尽管研究人员一直在积极寻求解决方案来减小变压器组件的尺寸并修剪注意力头等元素&#xff0c;但另一个关…

自动化测试01

测试脚本编写参考 selenium IDE 插件&#xff0c;firefox浏览器搜索安装&#xff0c;&#xff08;无法安装&#xff09; katalon recorder 负责输出脚本&#xff0c;输出模式&#xff0c;python2unitest &#xff0c; 无法输出python3类型脚本&#xff0c;仅参考 开发者工具 …

Ubuntu安装Android Studio

一、Android Studio安装 官方教程&#xff1a;安装 Android Studio | Android Developers 1、下载&#xff1a;Download Android Studio & App Tools - Android Developers&#xff0c;选择linux版本 2、 提取/解压 将下载的安装包提取出来 3、 64位ubuntu系统&#…

三分钟创建扫码查分系统

学生考试的成绩是家长和学生关注的重要问题。传统的成绩查询方式往往需要将整个成绩表格发到群里&#xff0c;不仅操作繁琐&#xff0c;而且可能导致信息泄露。为了解决这个问题&#xff0c;易查分应运而生。易查分是一个可以将Excel表格转换为在线查询的工具&#xff0c;可以轻…

Python——操作MySQL数据库

&#x1f60a;Python——操作MySQL数据库 &#x1f680;前言&#x1f50d;数据库编程&#x1f36d;数据库编程基本介绍&#x1f36d;数据库编程接口&#x1f36d;什么情况下会使用Python操作MySQL数据库&#xff1f;&#x1f36d;Java和Python操作MySQL数据库有何不同&#xff…

基于Python开发的AI智能联系人管理程序(源码+可执行程序+程序配置说明书+程序使用说明书)

一、项目简介 本项目是一套基于Python开发的AI智能联系人管理程序&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Python学习者。 包含&#xff1a;项目源码、项目文档等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#…

我的个人网站——宏夏Coding上线啦

网站地址&#xff1a;宏夏Coding Github地址&#xff1a;&#x1f525;&#x1f525;宏夏coding网站&#xff0c;致力于为编程学习者、互联网求职者提供最需要的内容&#xff01;网站内容包括求职秘籍&#xff0c;葵花宝典&#xff08;学习笔记&#xff09;&#xff0c;资源推…

核心实验18_ospf高级_ENSP

项目场景&#xff1a; 核心实验18_ospf高级_ENSP 多区域虚链路 实搭拓扑图&#xff1a; 具体操作&#xff1a; R1: [R1]ospf 1 router-id 1.1.1.1 [R1-ospf-1]area 0 [R1-ospf-1-area-0.0.0.0]net 1.1.1.0 0.0.0.255 [R1-ospf-1-area-0.0.0.0]net 10.1.12.0 0.0.0.255 [R1-os…

苹果电脑显示器校准推荐 BetterDisplay Pro for Mac

BetterDisplay Pro是一款Mac平台上的显示器校准软件&#xff0c;可以帮助用户调整显示器的颜色和亮度&#xff0c;以获得更加真实、清晰和舒适的视觉体验。 以下是BetterDisplay Pro的主要特点&#xff1a; - 显示器校准&#xff1a;可以根据不同的需求和环境条件调整显示器的颜…

车载多通道语音识别挑战赛(ICMC-ASR)丨ICASSP2024

由希尔贝壳、理想汽车、西工大音频语音与语言处理研究组、新加坡南洋理工大学、天津大学、WeNet开源社区、微软、中国信通院等单位发起的“车载多通道语音识别挑战赛”&#xff08;ICMC-ASR&#xff09;将作为IEEE声学、语音与信号处理国际会议&#xff08;ICASSP2024&#xff…

随机数问题

你知道 C 中的 rand() 函数是怎么实现的吗&#xff1f;你知道怎么在一维 / 二维 / 三维空间中等可能地随机取点吗&#xff1f; 随机数是一系列看似无规律、无法预测的数字或值的序列&#xff0c;其产生过程具有一定程度的不确定性。在计算机中&#xff0c;真正的绝对随机数是很…

当你的公司突然开始大量的裁员,被留下的你,真的准备好面对以后了吗?

留下来的&#xff0c;也是迷茫的 最近公司突然开始大量裁员&#xff0c;裁了一多半&#xff0c;作为唯一留下的APP 端开发人员&#xff0c;也开始陷入了焦虑&#xff0c;开始了思考&#xff0c;未来究竟何去何从&#xff0c;是否再去转到原生&#xff0c;从事原生的开发工作&a…

元服务那些事儿 | 挥剑解决隐私声明,激发开发豪情

话说元服务初上的年间&#xff0c;鸿蒙江湖高手云起&#xff0c;都是一顿键盘手猛敲&#xff0c;元服务推陈出新&#xff0c;创意层出不穷&#xff0c;无不风生水起。 江湖规矩&#xff1a;每个元服务必须提供规范的隐私声明&#xff0c;否则提交元服务发布上架后&#xff0c;将…