C++进阶之路---我们在何种情况下使用set和map

news2025/1/14 18:19:26

顾得泉:个人主页

个人专栏:《Linux操作系统》 《C++从入门到精通》  《LeedCode刷题》

键盘敲烂,年薪百万!


前言

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

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

       键值对:用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息

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


一、set

1.set的介绍

       使用我们的神器工具cplusplus,链接:set文档介绍

翻译:

       1.set是按照一定次序存储元素的容器
       2.在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的。set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们。
       3.在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行排序。
       4.set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对子集进行直接迭代。
       5.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中查找某个元素,时间复杂度为log2​n
       7.set中的元素不允许修改。
       8.set中的底层使用二叉搜索树(红黑树)来实现。

2.set的使用

1.set的模板参数列表

        T: set中存放元素的类型,实际在底层存储<value, value>的键值对。

        Compare:set中元素默认按照小于来比较

        Alloc:set中元素空间的管理方式,使用STL提供的空间配置器管理

2.set的构造

函数声明
功能介绍
set (const Compare& comp = Compare(), const Allocator& = Allocator() );
构造空的 set
set (InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator() );
[first, last) 间中的元素构造 set
set ( const set<Key,Compare,Allocator>& x);
set 的拷贝构造

3.set的迭代器

函数声明
功能介绍
iterator begin()
返回 set 中起始位置元素的迭代器
iterator end()
返回 set 中最后一个元素后面的迭代器
const_iterator cbegin()  const
返回 set 中起始位置元素的 const 迭代器
const_iterator cend() const
返回 set 中最后一个元素后面的 const 迭代器
reverse_iterator rbegin()
返回 set 第一个元素的反向迭代器,即 end
reverse_iterator rend()
返回 set 最后一个元素下一个位置的反向迭代器, rbegin
const_reverse_iterator
crbegin() const
返回 set 第一个元素的反向 const 迭代器,即 cend
const_reverse_iterator
crend() const
返回 set 最后一个元素下一个位置的反向 const 代器,即 crbegin

4.set的容量

函数声明
功能介绍
bool empty ( ) const
检测 set 是否为空,空返回 true ,否则返回 true
size_type size() const
返回 set 中有效元素的个数

5.set的修改 

函数声明
功能介绍
pair<iterator,bool> insert (
const value_type& x )
set 中插入元素 x ,实际插入的是 <x, x> 构成的 键值对,如果插入成功,返回 < 该元素在 set 中的 位置, true>, 如果插入失败,说明 x set 中已经 存在,返回 <x set 中的位置, false>
void erase ( iterator position )
删除 set position 位置上的元素
size_type erase ( const
key_type& x )
删除 set 中值为 x 的元素,返回删除的元素的个数
void erase ( iterator first,
iterator last )
删除 set [first, last) 区间中的元素
void swap (
set<Key,Compare,Allocator>&
st );
交换 set 中的元素
void clear ( )
set 中的元素清空
iterator find ( const
key_type& x ) const
返回 set 中值为 x 的元素的位置
size_type count ( const
key_type& x ) const
返回 set 中值为 x 的元素的个数

6.set的使用

#include <set>
void TestSet()
{ 
     // 用数组array中的元素构造set
     int array[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0, 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
     set<int> s(array, array+sizeof(array)/sizeof(array));
     cout << s.size() << endl;
     // 正向打印set中的元素,从打印结果中可以看出:set可去重
     for (auto& e : s)
     cout << e << " ";
     cout << endl;
     // 使用迭代器逆向打印set中的元素
     for (auto it = s.rbegin(); it != s.rend(); ++it)
     cout << *it << " ";
     cout << endl;
     // set中值为3的元素出现了几次
     cout << s.count(3) << endl;
}

2、map

1.map的介绍

       使用我们的神器工具cplusplus,链接:map的文档简介

翻译:

       1.map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元素。
       2.在map中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型value_type绑定在一起,为其取别名称为pair:typedef pair<const key, T> value_type;
       3.在内部,map中的元素总是按照键值key进行比较排序的。
       4.map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)。
       5.map支持下标访问符,即在[]中放入key,就可以找到与key对应的value。
       6.map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))。

2.map的使用

1.map的模板参数说明

       key: 键值对中key的类型

       T: 键值对中value的类型

       Compare: 比较器的类型,map中的元素是按照key来比较的,缺省情况下按照小于来比较,一般情况下(内置类型元素)该参数不需要传递,如果无法比较时(自定义类型),需要用户自己显式传递比较规则(一般情况下按照函数指针或者仿函数来传递)

       Alloc:通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标准库提供的空间配置器。

注意:在使用map时,需要包含头文件 #include<map>

2.map的构造

函数声明
功能介绍
map()
构造一个空的 map

3.map的迭代器

函数声明
功能介绍
begin() end()
begin: 首元素的位置, end 最后一个元素的下一个位置
cbegin() cend()
begin end 意义相同,但 cbegin cend 所指向的元素不 能修改
rbegin() rend()
反向迭代器, rbegin end 位置, rend begin 位置,其 ++ -- 操作与 begin end 操作移动相反
crbegin() crend()
rbegin rend 位置相同,操作相同,但 crbegin crend 指向的元素不能修改

4.map的容量与元素访问

函数声明
功能简介
bool empty ( ) const
检测 map 中的元素是否为空,是返回
true ,否则返回 false
size_type size() const
返回 map 中有效元素的个数
mapped_type& operator[] (const key_type& k)
返回去 key 对应的 value

 问题:当key不在map中时,通过operator获取对应value时会发生什么问题?

注意:在元素访问时,有一个与operator[]类似的操作at()(该函数不常用)函数,都是通过key找到与key对应的value然后返回其引用,不同的是:当key不存在时,operator[]用默认value与key构造键值对然后插入,返回该默认value,at()函数直接抛异常。

5.map中元素的修改

函数声明
功能简介
pair<iterator,bool> insert (
const value_type& x )
map 中插入键值对 x ,注意 x 是一个键值 对,返回值也是键值对: iterator 代表新插入 元素的位置, bool 代表释放插入成功
void erase ( iterator position )
删除 position 位置上的元素
size_type erase ( const
key_type& x )
删除键值为 x 的元素
void erase ( iterator first,
iterator last )
删除 [first, last) 区间中的元素
void swap ( map<Key,T,Compare,Allocator>&
mp )
交换两个 map 中的元素
void clear ( )
map 中的元素清空
iterator find ( const key_type& x
)
map 中插入 key x 的元素,找到返回该元
素的位置的迭代器,否则返回 end
const_iterator find ( const
key_type& x ) const
map 中插入 key x 的元素,找到返回该元 素的位置的 const 迭代器,否则返回 cend
size_type count ( const
key_type& x ) const
返回 key x 的键值在 map 中的个数,注意 map key 是唯一的,因此该函数的返回值 要么为 0 ,要么为 1 ,因此也可以用该函数来 检测一个 key 是否在 map
#include <string>
#include <map>
void TestMap()
{
     map<string, string> m;
     // 向map中插入元素的方式:
     // 将键值对<"peach","桃子">插入map中,用pair直接来构造键值对
     m.insert(pair<string, string>("peach", "桃子"));
     // 将键值对<"peach","桃子">插入map中,用make_pair函数来构造键值对
     m.insert(make_pair("banan", "香蕉"));
 
     // 借用operator[]向map中插入元素
     /*
      operator[]的原理是:
      用<key, T()>构造一个键值对,然后调用insert()函数将该键值对插入到map中
      如果key已经存在,插入失败,insert函数返回该key所在位置的迭代器
      如果key不存在,插入成功,insert函数返回新插入元素所在位置的迭代器
      operator[]函数最后将insert返回值键值对中的value返回
     */
    // 将<"apple", "">插入map中,插入成功,返回value的引用,将“苹果”赋值给该引用结果,
     m["apple"] = "苹果";
     // key不存在时抛异常
     //m.at("waterme") = "水蜜桃";
     cout << m.size() << endl;
     // 用迭代器去遍历map中的元素,可以得到一个按照key排序的序列
     for (auto& e : m)
         cout << e.first << "--->" << e.second << endl;
     cout << endl;
     // map中的键值对key一定是唯一的,如果key存在将插入失败
     auto ret = m.insert(make_pair("peach", "桃色"));
     if (ret.second)
         cout << "<peach, 桃色>不在map中, 已经插入" << endl;
     else
         cout << "键值为peach的元素已经存在:" << ret.first->first << "--->"
        << ret.first->second <<" 插入失败"<< endl;
     // 删除key为"apple"的元素
     m.erase("apple");
     if (1 == m.count("apple"))
         cout << "apple还在" << endl;
     else
         cout << "apple被吃了" << endl;
 }

3.总结

       1.map中的的元素是键值对
       2.map中的key是唯一的,并且不能修改
       3.默认按照小于的方式对key进行比较
       4.map中的元素如果用迭代器去遍历,可以得到一个有序的序列
       5.map的底层为平衡搜索树(红黑树),查找效率比较高O(log2​N)
       6.支持[]操作符,operator[]中实际进行插入查找。


结语:C++关于如何使用set和map的分享到这里就结束了,希望本篇文章的分享会对大家的学习带来些许帮助,如果大家有什么问题,欢迎大家在评论区留言~~~ 

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

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

相关文章

【多智能体强化学习02---训练范式+独立学习+多智能体策略梯度算法】

文章目录 多智能体强化学习训练和执行范式CTCEDTDECTDE MARL符号表示分布式学习&#xff08;Independent Learning)基于值函数的分布式学习&#xff08;Independent value-based learning)基于策略梯度的分布式学习&#xff08;Independent policy gradient learning) 多智能体…

力扣:数组篇

1、数组理论基础 数组是存放在连续内存空间上的相同类型数据的集合。 需要两点注意的是 数组下标都是从0开始的。数组内存空间的地址是连续的 因为数组的在内存空间的地址是连续的&#xff0c;所以我们在删除或者增添元素的时候&#xff0c;就难免要移动其他元素的地址。 …

LLM之RAG实战(二十九)| 探索RAG PDF解析

对于RAG来说&#xff0c;从文档中提取信息是一种不可避免的场景&#xff0c;确保从源文件中提取出有效的内容对于提高最终输出的质量至关重要。 文件解析过程在RAG中的位置如图1所示&#xff1a; 在实际工作中&#xff0c;非结构化数据比结构化数据丰富得多。如果这些海量数据无…

免费视频背景素材下载

找免费视频素材、背景就上这6个网站&#xff0c;高质量&#xff0c;无版权可商用。 1、菜鸟图库 https://www.sucai999.com/video.html?vNTYwNDUx 菜鸟图库虽然是个设计素材网站&#xff0c;但除了设计类素材之外还有很多视频、音频、办公类等素材&#xff0c;视频素材就有上…

课堂行为动作识别数据集

一共8884张图片 xml .txt格式都有 Yolo可直接训练 已跑通 动作类别一共8类。 全部为教室监控真实照片&#xff0c;没有网络爬虫滥竽充数的图片&#xff0c;可直接用来训练。以上图片均一一手工标注&#xff0c;标签格式为VOC格式。适用于YOLO算法、SSD算法等各种目标检测算法…

自主通用多物理场仿真PaaS平台伏图(Simdroid)及伏图电子散热模块上架华为云商店

随着云计算、大数据等前沿技术的蓬勃发展&#xff0c;国内制造业正面临智能制造转型升级的机遇与挑战。工业软件是制造业研发创新不可或缺的核心工具&#xff0c;《“十四五”智能制造发展规划》中明确了工业软件对于智能制造的核心支撑作用&#xff0c;着重提出加强关键核心技…

DevOps方案中10款最佳开源监控工具

DevOps方案中10款最佳开源监控工具 2024年,监视对现代DevOps团队的工作至关重要。DevOps团队需要可靠且灵活的工具,以有效监视和管理复杂系统,这些系统可以提供有关系统性能、可用性和安全性的实时见解。 开源监控工具由于其成本效益、灵活性和社区支持而日益受到青睐。 …

MySQL教程-SQL

SQL(Structured Query Language)结构化查询语言&#xff0c;操作关系型数据库的编程语言&#xff0c;定义了一套操作关系型数据库统一标准。 语法 SQL语句可以单行或多行书写&#xff0c;以;为结束标记SQL可以使用空格或缩进来增强语句的可读性SQL分单行注释(-- 注释内容 或 …

景略JL5104-N048C 可P2P代替RTL8304MB

话不多说&#xff0c;直接上参数&#xff0c;可免费申请样片上机测试。 JL5104是一个带有RMIl接口的4端口快速以太网交换机。 它支持四级优先级队列的QoS功能&#xff0c;保证了一些实时网络应用的性能。 JL5104集成了一个2k入口地址查找表和一个4路关联散列算法&#xff0c;该…

ios xcode 15 PrivacyInfo.xcprivacy 隐私清单 查询应用使用的隐私api

1.需要升级mac os系统到13 兼容 xcode 15.1 2.升级mac os系统到14 兼容 xcode 15.3 3.选择 New File 4.直接搜索 privacy 能看到有个App Privacy 5.右击Add Row 7.直接选 Label Types 8.选中继续添加就能添加你的隐私清单了 苹果官网文档

稀碎从零算法笔记Day15-LeetCode:判断子序列

跑样例的时候LC炸了&#xff0c;以为今天回断更 题型&#xff1a;字符串、双指针 链接&#xff1a;392. 判断子序列 - 力扣&#xff08;LeetCode&#xff09; 来源&#xff1a;LeetCode 题目描述&#xff08;此题建议结合样例理解&#xff09; 给定字符串 s 和 t &#xf…

鸿蒙Socket通信示例(TCP通信)

前言 DevEco Studio版本&#xff1a;4.0.0.600 参考链接&#xff1a;OpenHarmony Socket 效果 TCPSocket 1、bind绑定本地IP地址 private bindTcpSocket() {let localAddress resolveIP(wifi.getIpInfo().ipAddress)console.info("111111111 localAddress: " …

性能测试总结 —— 测试流程篇!

本文主要介绍下性能测试的基本流程&#xff0c;性能测试从实际执行层面来看&#xff0c;测试的过程一般分为这么几个阶段&#xff0c;如下图&#xff1a;       下面分别介绍下每个阶段具体需要做什么&#xff1a; 一、性能需求分析&#xff1a; 性能需求分析是整个性能…

【PLC】现场总线和工业以太网汇总

1、 现场总线 1.1 什么是现场总线 1&#xff09;非专业描述&#xff1a; 如下图&#xff1a;“人机界面”一般通过以太网连接“控制器(PLC)”&#xff0c;“控制器(PLC)”通过 “现场总线”和现场设备连接。 2&#xff09;专业描述&#xff08;维基百科&#xff09; 现场总线…

MTK安卓开发板_联发科开发板评估套件_安卓主板硬件开发

在介绍开发板之前&#xff0c;让我们先来区分一下核心板和开发板的区别。核心板是一种集成度高、功能完整的计算模块&#xff0c;搭载系统&#xff0c;简化了外围接口&#xff0c;体积尺寸相对较小&#xff0c;主要适用于嵌入式系统。而开发板由核心板底板组成&#xff0c;提供…

探索直播美颜SDK的未来发展方向:虚拟现实、增强现实与混合

如今&#xff0c;随着虚拟现实&#xff08;VR&#xff09;、增强现实&#xff08;AR&#xff09;和混合现实&#xff08;MR&#xff09;等技术的不断发展&#xff0c;直播美颜SDK的未来发展方向也将面临着更多的可能性和挑战。今天我将与大家共同探讨直播美颜SDK在虚拟现实、增…

国科大网络行为学导论代码作业--更新中

一、Xray安装 参考自&#xff1a;Xray的安装与使用&#xff08;超详细&#xff09;_xray使用教程-CSDN博客 下载网址&#xff1a;Releases chaitin/xray GitHub 解压 双击安装 生成证书 cd到xray目录&#xff0c;生成证书 复制链接 然后cd到xray目录 .\xray_windows_amd6…

Ubuntu 14.04:PaddleOCR基于PaddleHub Serving的服务部署(失败)

目录 一、为什么使用一键服务部署 二、安装 paddlehub 1.8 2.1 安装前的环境准备 2.2 安装paddlehub 1.8 2.2.1 安装paddlehub 2.2.2 检测安装是否成功 2.2.3 检查本地与远端PaddleHub-Server的连接状态 2.2.4 测试使用 2.3 其他 2.3.1 如何卸载、pip常用命令、常见…

WRF模型运行教程(ububtu系统)--II.ARWpost安装

一、ARWpost简介 ARWpost 是一个把 WRF 结果转为 GrADS 或 Vis5D 可以辨识的数据格式的软件&#xff0c;就是WRF运行结束以后&#xff0c;把WRF的结果变成咱们平时比较常用的数据格式。 二、下载和安装ARWpos_V3 1.ARWpos_V3安装前准备 # 进入Build_WRF文件夹 cd Build_WRF …

代码随想录刷题笔记-Day33

1. 跳跃游戏 55. 跳跃游戏https://leetcode.cn/problems/jump-game/ 给你一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标&#xff0c;如果可以&#xff0c;返回 tru…