当前位置: 首页 > news >正文

【深入C++】map和set的使用

文章目录

  • C++ 中的容器分类
    • 1. 顺序容器
    • 2. 关联容器
    • 3. 无序容器
    • 4. 容器适配器
    • 5. 字符串容器
    • 6. 特殊容器
  • set
    • 1.构造函数
    • 2.迭代器
    • 3.容量相关的成员函数
    • 4.修改器类的成员函数
    • 5.容器相关操作的成员函数
  • multiset
    • 1.equal_range
  • map
    • 1.初始化相关的函数
    • 2.迭代器
    • 3.容量相关的成员函数
    • 4.访问相关的成员函数
    • 5.修改器类的成员函数
    • 6.容器相关操作的成员函数
  • 总结

在这里插入图片描述

在这里插入图片描述

C++ 中的容器分类

在C++中,标准库提供了多种容器,这些容器可以根据其数据存储方式和功能进行分类。以下是C++中常见容器的分类:

1. 顺序容器

这些容器按顺序存储元素,适用于需要保持元素顺序的场景。

  • vector: 动态数组,支持快速随机访问和在末尾高效插入和删除操作。
  • deque: 双端队列,支持快速随机访问和在两端高效插入和删除操作。
  • list: 双向链表,支持在任何位置高效插入和删除操作,但随机访问较慢。
  • forward_list: 单向链表,只支持在头部高效插入和删除操作。
  • array: 固定大小的数组,大小在编译时确定。

2. 关联容器

这些容器根据键值对存储元素,并自动按键排序,适用于需要快速查找的场景。

  • set: 集合,存储唯一的元素,元素自动按键排序。
  • multiset: 允许重复元素的集合,元素自动按键排序。
  • map: 键值对存储的映射,键唯一且自动排序。
  • multimap: 允许重复键的映射,键自动排序。

3. 无序容器

这些容器使用哈希表存储元素,适用于需要快速查找和插入的场景,但不保证元素顺序。

  • unordered_set: 无序集合,存储唯一的元素。
  • unordered_multiset: 无序多重集合,允许重复元素。
  • unordered_map: 无序映射,键唯一。
  • unordered_multimap: 无序多重映射,允许重复键。

4. 容器适配器

这些不是独立的容器,而是对现有容器的包装,提供特定用途的接口。

  • stack: 栈,后进先出(LIFO)结构,通常使用deque或vector实现。
  • queue: 队列,先进先出(FIFO)结构,通常使用deque或list实现。
  • priority_queue: 优先队列,元素按优先级排序,通常使用vector和heap算法实现。

5. 字符串容器

  • string: 用于存储和操作字符序列,类似于动态数组,但专门针对字符。

6. 特殊容器

  • bitset: 固定大小的二进制数组,提供按位操作。

这些容器各有优缺点和适用场景,选择合适的容器可以显著提高程序的性能和可维护性。

这篇文章讲的两个容器都是关联式容器

set

在这里插入图片描述
在C++标准库中,set容器的底层实现通常是基于红黑树这种自平衡二叉搜索树。红黑树是一种能够在插入、删除和查找操作中保持对数时间复杂度的树结构。

1.构造函数

在这里插入图片描述
构造函数主要分为三个:无参构造,迭代器区间构造,拷贝构造

无参构造:

set<int> s;

迭代器区间构造:

vector<int>  v{ 1,2,3,4,5,6,7 };
set<int> s(v.begin(), v.end());

拷贝构造:

set<int> s1{ 1,2,3,4 };
set<int> s2(s1);

赋值拷贝

set<int> s1{ 1,2,3,4 };
set<int> s2;
s2 = s1;

2.迭代器

在这里插入图片描述

迭代器遍历:

auto it = s1.begin();
while (it != s1.end())
{cout << *it << ' ';it++;
}

范围for:

for (auto e : s1)
{cout << e << ' ';
}

3.容量相关的成员函数

在这里插入图片描述

int main()
{set<int> s1{ 1,2,3,4 };cout << s1.size() << endl;//4cout << s1.empty() << endl;//0return 0;
}

4.修改器类的成员函数

在这里插入图片描述
insert:
有三个重载函数
在这里插入图片描述

支持迭代器区间插入。

int main()
{set<int> s1;s1.insert(2);s1.insert(3);s1.insert(6);s1.insert(1);s1.insert(5);s1.insert(7);for (auto e : s1){cout << e << ' ';}return 0;
}

erase:
在这里插入图片描述

第二个重载函数:

int num = s1.erase(3);
cout << endl << num << endl;

删除成功返回1,删除失败返回0。

5.容器相关操作的成员函数

在这里插入图片描述
find:

int main()
{set<int> s1;s1.insert(2);s1.insert(3);s1.insert(6);s1.insert(1);s1.insert(5);s1.insert(7);auto it = s1.find(2);if (it != s1.end()) cout << *it << endl;else cout << "does not exist" << endl;return 0;
}

如果找到了返回找到的迭代器,如果没有找到则返回的是end()。
count:
count返回的是对应元素的个数:在set中存在就返回1,不存在就返回0。
在这里插入图片描述
lower_bound:

lower_bound返回的是大于等于某个数的。

int main()
{set<int> s1;s1.insert(2);s1.insert(3);s1.insert(6);s1.insert(1);s1.insert(5);s1.insert(7);auto lower = s1.lower_bound(4);cout << *lower << endl;return 0;
}

这里输出的是大于等于4的数,所以这里输出的是5。
upper_bound:

auto upper = s1.upper_bound(6);
cout << *upper << endl;

这里输出的是大于6的数,所以输出的是7。
set有一个致命的缺陷,在插入重复数据时,是插入不进去的,所以这里我们需要了解multiset。

multiset

在这里插入图片描述

multiset和set唯一不同的区别是一个支持插入重复数据,一个不支持。

int main()
{set<int> s1;s1.insert(1);s1.insert(1);s1.insert(1);s1.insert(1);for (auto e : s1) cout << e << ' ';multiset<int> s2;s2.insert(1);s2.insert(1);s2.insert(1);s2.insert(1);cout << endl;for (auto e : s2)cout << e << ' ';return 0;
}

可以set不支持插入重复数据,multiset支持插入重复数据。
在这里插入图片描述
在查找数据的时候multiset查找的是第一个数据。
删除数据:multiset删除数据,删除的是所有重复的数据,而不是删除第一个数据。

1.equal_range

int main()
{multiset<int> s{ 1,1,4,4,4,3,3,3,3,3,5,5,5, 6 };auto [a, b] = s.equal_range(3);s.erase(a, b);for (auto e : s){cout << e << ' ';}
}

equal_range可以求出指定值的范围区域,两个迭代器。
一个首一个尾。

map

在这里插入图片描述
map属于KV模型,用一个k值索引v值。
在C++标准库中,map 容器的底层实现通常是基于红黑树(Red-Black Tree)这种自平衡二叉搜索树(Self-balancing Binary Search Tree)。红黑树是一种能够在插入、删除和查找操作中保持对数时间复杂度的树结构。

1.初始化相关的函数

在这里插入图片描述

构造函数:
在这里插入图片描述
map和set的构造方式是一样的,也是三种构造函数。

2.迭代器

在这里插入图片描述
map的迭代器和set的迭代器稍有区别,但不多。

返回for:

int main()
{map<int, char> m{ { 1,'a' } ,{ 2,'b' },{ 3,'c' },{ 4,'d' },{ 5,'e' } };for (auto e : m)cout << e.first << ':' << e.second << endl;
}

迭代器区间遍历:

int main()
{map<int, char> m{ { 1,'a' } ,{ 2,'b' },{ 3,'c' },{ 4,'d' },{ 5,'e' } };auto it = m.begin();while (it != m.end()){cout << it->first << ':' << it->second << endl;it++;}
}

结构化绑定:

int main()
{map<int, char> m{ { 1,'a' } ,{ 2,'b' },{ 3,'c' },{ 4,'d' },{ 5,'e' } };for (auto [a, b] : m)cout << a << ':' << b << endl;
}

3.容量相关的成员函数

在这里插入图片描述
和set的用法大差不差。

4.访问相关的成员函数

在这里插入图片描述
operator[]:

int main()
{map<int, char> m{ { 1,'a' } ,{ 2,'b' },{ 3,'c' },{ 4,'d' },{ 5,'e' } };cout << m[1] << endl;cout << m[2] << endl;cout << m[3] << endl;
}

map可以通过一个成员的第一个键值来索引当前成员的第二个键值,就是用key索引value。
at:

int main()
{map<int, char> m{ { 1,'a' } ,{ 2,'b' },{ 3,'c' },{ 4,'d' },{ 5,'e' } };cout << m.at(1) << endl;
}

用at进行索引value。
在这里插入图片描述
可以看见如果容器当中没有当前值的索引,则会抛出异常。

5.修改器类的成员函数

在这里插入图片描述
这里修改器类的成员函数和set相同,但是insert,需要插入一个键值对:

m.insert({ 6,'f' });
m.insert(pair<int, char>(6, 'f'));
m.insert(make_pair(6, 'f'));

6.容器相关操作的成员函数

在这里插入图片描述
这些和set都是一样的。

总结

在本篇博客中,我们深入探讨了C++标准库中的mapset容器。通过详细的示例和解释,我们了解了它们的基本用法、常用操作以及在不同场景下的应用。mapset不仅为我们提供了高效的键值对存储和有序集合管理功能,还在复杂数据结构和算法设计中扮演了重要角色。

掌握mapset的使用,不仅能够提升我们的编程效率,还能帮助我们编写出更为高效和可靠的代码。在实际开发中,合理地选择和使用这些容器,可以显著优化程序的性能和可维护性。

希望通过这篇博客,大家能够对mapset有更深入的理解,并在以后的编程实践中灵活运用它们。如果你有任何疑问或建议,欢迎在评论区留言讨论。

相关文章:

【深入C++】map和set的使用

文章目录 C 中的容器分类1. 顺序容器2. 关联容器3. 无序容器4. 容器适配器5. 字符串容器6. 特殊容器 set1.构造函数2.迭代器3.容量相关的成员函数4.修改器类的成员函数5.容器相关操作的成员函数 multiset1.equal_range map1.初始化相关的函数2.迭代器3.容量相关的成员函数4.访问…...

跟代码执行流程,读Megatron源码(二)训练入口pretrain_gpt.py

Megatron-LM默认支持GPT、T5、BERT等多个常见模型的预训练&#xff0c;当下大模型流行&#xff0c;故以pretrain_gpt.py为例做源码的走读。 一. 启动pretrain_gpt.py pretrain_gpt.py为GPT类模型的训练入口&#xff0c;它通过命令行形式被调用&#xff0c;其精确执行路径位于M…...

MATLAB练习题——矩阵(2)

逻辑运算 a [5 0.2 0 -8 -0.7 ]&#xff0c;在进行逻辑运算时&#xff0c;a 相当于什么样的逻辑量。 相当于 a[1 1 0 1 1] 角度运算 在 sin(x)运算中&#xff0c;x 是角度还是弧度&#xff1f; 在 sin(x)运算中&#xff0c;x 是弧度&#xff0c;MATLAB 规定所有…...

arm、AArch64、x86、amd64、x86_64 的区别

arm vs AArch64 vs amd64 vs x86_64 vs x86 的区别 当涉及到 CPU 的时候&#xff0c;有许多术语&#xff1a;AArch64、x86_64、amd64、arm 等等。了解它们是什么以及它们之间的区别。 当你查看数据表或软件下载页面时是否被 ARM、AArch64、x86_64、i386 等术语混淆&#xff1f;…...

【SpringBoot】 jasypt配置文件密码加解密

目前我们对yml配置文件中的密码都是明文显示&#xff0c;显然这不安全&#xff0c;有的程序员离职了以后可能会做一些非法骚操作&#xff0c;所以我们最好要做一个加密&#xff0c;只能让领导架构师或者技术经理知道这个密码。所以这节课就需要来实现一下。 我们可以使用jasypt…...

复杂网络的任意子节点的网络最短距离

复杂网络的任意子节点的网络最短距离 题目要求介绍 本文算法测试用的数据集为空手道俱乐部&#xff0c;其中空手道俱乐部的数据集可通过这个链接进行下载•http://vlado.fmf.uni-lj.si/pub/networks/data/Ucinet/UciData.htm#zachary 摘要 本文旨在解决复杂网络中任意子节点…...

(Qt) 文件读写基础

文章目录 &#x1f5c2;️前言&#x1f4c4;ref&#x1f4c4;访问标记&#x1f5c3;️enum 标记 &#x1f5c2;️Code&#x1f4c4;demo&#x1f4c4;分点讲解&#x1f5c3;️继承体系&#x1f5c3;️打开/关闭&#x1f5c3;️写&#x1f5c3;️读 &#x1f5c2;️END&#x1f…...

全产业布局对穿戴甲品牌连锁店的意义

对于美甲行业来说&#xff0c;穿戴甲虽然不是什么新生事物&#xff0c;但也就是近两年才流行开来。面对井喷的市场需求&#xff0c;相应的从业者&#xff0c;不管是品牌连锁店&#xff0c;还是做批发、外贸&#xff0c;美甲周边、亦或是OEM的&#xff0c;大家都忙得不亦乐乎&am…...

git的一些使用技巧(git fetch 和 git pull的区别,git merge 和 git rebase的区别)

最近闲来无聊&#xff0c;虽然会使用git操作&#xff0c;但是 git fetch 和 git pull 的区别&#xff0c;git merge 和 git rebase的区别只是一知半解&#xff0c;稍微研究一下&#xff1b; git fetch 和 git pull 的区别 git fetch git fetch 是将远程仓库中的改动拉到本地…...

展厅中控系统有哪些优势呢

格芬科技的展厅中控系统具有多方面的优势&#xff0c;主要体现在以下几个方面&#xff1a; 一、高度集成与灵活控制 全终端网络可编程&#xff1a;格芬科技的展厅中控系统采用全终端网络可编程技术&#xff0c;能够实现对展厅内各种设备的集中控制和管理&#xff0c;包括电脑…...

FPGA开发在verilog中关于阻塞和非阻塞赋值的区别

一、概念 阻塞赋值&#xff1a;阻塞赋值的赋值号用“”表示&#xff0c;对应的是串行执行。 对应的电路结构往往与触发沿没有关系&#xff0c;只与输入电平的变化有关系。阻塞赋值的操作可以认为是只有一个步骤的操作&#xff0c;即计算赋值号右边的语句并更新赋值号左边的语句…...

动态特征转换的艺术:在Mojo模型中实现自定义变换的策略

动态特征转换的艺术&#xff1a;在Mojo模型中实现自定义变换的策略 在机器学习中&#xff0c;特征转换是数据预处理的关键步骤&#xff0c;它直接影响模型的性能和结果的准确性。Mojo模型&#xff0c;作为一种高效的模型部署形式&#xff0c;允许在不同环境中运行模型并进行预…...

如何让Python爬虫在遇到异常时继续运行

概述 在数据收集和数据挖掘中&#xff0c;爬虫技术是一项关键技能。然而&#xff0c;爬虫在运行过程中不可避免地会遇到各种异常情况&#xff0c;如网络超时、目标网站变化、数据格式不一致等。如果不加以处理&#xff0c;这些异常可能会导致爬虫程序中断&#xff0c;影响数据…...

手把手带你搭建Snort入侵检测系统

在当今数字化社会&#xff0c;网络安全问题日益突出。为了有效防范网络攻击&#xff0c;部署入侵检测系统&#xff08;IDS&#xff09;是必要的防护措施。Snort作为一款功能强大的开源IDS工具&#xff0c;被广泛应用于各种网络环境中。本文将手把手教您如何从零开始实现Snort入…...

小程序内嵌uniapp页面跳转回小程序指定页面方式

使用微信小程序提供的Api&#xff1a;wx.miniProgram.navigateTo 在小程序中嵌套uniapp的H5页面&#xff0c;并使用wx.miniProgram.navigateTo进行页面跳转&#xff0c;需要确保满足以下条件&#xff1a; 你的小程序必须是通过uniapp构建的&#xff0c;并且支持小程序嵌套。 你…...

基于 Three.js 的 3D 模型加载优化

作者&#xff1a;来自 vivo 互联网前端团队- Su Ning 作为一个3D的项目&#xff0c;从用户打开页面到最终模型的渲染需要经过多个流程&#xff0c;加载的时间也会比普通的H5项目要更长一些&#xff0c;从而造成大量的用户流失。为了提升首屏加载的转化率&#xff0c;需要尽可能…...

Jlink下载与适配keil ccs theia教程 用jlink代替ti自己的下载仿真器

用jlink代替ti自己的下载仿真器&#xff0c;然后你去买立创的m0g3507才19.9包赚160 安装 J-Link 软件包 J-Link 软件包 v7.88i 或更高版本支持 MSPM0。 从 Segger 网站下载安装程序 按照安装程序说明操作 安装程序将自动请求更新 IAR 或 Keil&#xff08;如果已安装&#x…...

C# 进制之间的转换(二进制,八进制,十进制,十六进制)

常用的方法是&#xff1a;Convert.ToString(byte value, int toBase)&#xff0c; 并且有多个重载方法&#xff0c; value的类型可以为short&#xff0c;int 等&#xff0c;但必须是整数且不能为负数&#xff0c; 一般默认为十进制 toBase: 返回值的基数&#xff0c;必须是 2、…...

Linux 基础开发工具 : Vim编辑器

Vim 是 Linux 和其他类 Unix 系统上广泛使用的文本编辑器之一。它基于更早的 vi 编辑器&#xff0c;但添加了许多增强功能和扩展。Vim 是“Vi IMproved”的缩写&#xff0c;意为“改进的 Vi”&#xff0c;我们常使用Vim编辑器编写c/c代码。 ps&#xff1a;该篇介绍均为最基础介…...

Delphi 11.2 配置Android SDK 环境

打开 Delphi 11 点击 Tools–Options… 然后点击 Deployment–SDK Manager–Add… 这里如果配置64位就选 Android 64-bit&#xff0c;如果配置32位就选 Android 32-bit 点击 Select an SDK version–Add New… 有警告图标的就是有问题的项&#xff0c;需要手动更新一下&#xf…...

uniapp 对接腾讯云IM群组成员管理(增删改查)

UniApp 实战&#xff1a;腾讯云IM群组成员管理&#xff08;增删改查&#xff09; 一、前言 在社交类App开发中&#xff0c;群组成员管理是核心功能之一。本文将基于UniApp框架&#xff0c;结合腾讯云IM SDK&#xff0c;详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...

FFmpeg:Windows系统小白安装及其使用

一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】&#xff0c;注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录&#xff08;即exe所在文件夹&#xff09;加入系统变量…...

Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案

在大数据时代&#xff0c;海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构&#xff0c;在处理大规模数据抓取任务时展现出强大的能力。然而&#xff0c;随着业务规模的不断扩大和数据抓取需求的日益复杂&#xff0c;传统…...

抽象类和接口(全)

一、抽象类 1.概念&#xff1a;如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象&#xff0c;这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法&#xff0c;包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中&#xff0c;⼀个类如果被 abs…...

LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用

中达瑞和自2005年成立以来&#xff0c;一直在光谱成像领域深度钻研和发展&#xff0c;始终致力于研发高性能、高可靠性的光谱成像相机&#xff0c;为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...

小木的算法日记-多叉树的递归/层序遍历

&#x1f332; 从二叉树到森林&#xff1a;一文彻底搞懂多叉树遍历的艺术 &#x1f680; 引言 你好&#xff0c;未来的算法大神&#xff01; 在数据结构的世界里&#xff0c;“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的&#xff0c;它…...

云安全与网络安全:核心区别与协同作用解析

在数字化转型的浪潮中&#xff0c;云安全与网络安全作为信息安全的两大支柱&#xff0c;常被混淆但本质不同。本文将从概念、责任分工、技术手段、威胁类型等维度深入解析两者的差异&#xff0c;并探讨它们的协同作用。 一、核心区别 定义与范围 网络安全&#xff1a;聚焦于保…...