C++进阶篇章:set与map(pair , multiset , multimap)

目录

1.关联式容器与序列式容器

2.pair(键值对)

3.set

构造函数

find函数

count函数:

insert函数

4.multiset

5.map

insert函数

operator[]


1.关联式容器与序列式容器

C++中关联式容器与序列式容器是两种不同的容器

   1.关联式容器

关联式容器:

  1. 关联式容器主要包括 std::set, std::map, std::multiset, std::multimap 等。
  2. 这些容器是基于键值对(<key, value>结构)的概念,通过键==(key)来唯一标识元素==。
  3. 关联式容器内部使用二叉搜索树(通常是红黑树)或类似的数据结构,以保持元素的有序性。
  4. 插入、删除、查找等操作的平均时间复杂度是 O(log n)。

序列式容器:

  1. 序列式容器包括 std::vector, std::list, std::deque, std::array 等。
  2. 这些容器是基于线性结构的,元素在容器中的位置是由插入的顺序决定的。
  3. 插入、删除、查找等操作的平均时间复杂度因容器类型而异,但在最差情况下,可能达到 O(n)。

2.pair(键值对)

C++中有一种数据结构,他能将两种不同的数据类型给强制的绑定,形成相连关系

定义:pair包含在<utility> 的头文件中 ,其中pair中有两个成员变量 , 一个是first , 另一个就是second 

STL库中pair的定义(没有具体实现swap,make_pair等函数)

template <class T1, class T2>
struct pair
{T1 first;T2 second;pair(T1 a = T1() , T2 b = T2() ) //构造函数: first(a), second(b){}pair(const T1& a, const T2& b) //拷贝构造: first(a), second(b){}
};

pair的构造函数

1.构造函数

具体代码实现请看上面

实例:

#include<iostream>
#include<vector>
#include<string>
#include<map>
#include<queue>
#include<utility>
using namespace std;
int main()
{pair<int, int> t(1, 1);pair<int, int> k;cout << t.first << " " << t.second << endl;cout << k.first << " " << k.second << endl;return 0;
}

2.拷贝构造函数

#include<iostream>
#include<vector>
#include<string>
#include<map>
#include<queue>
#include<utility>
using namespace std;
int main()
{pair<int, int> t(1, 1);// 构造函数pair<int, int> k = t;// 拷贝构造函数pair<int, int> s(t);// 拷贝构造函数cout << t.first << " " << t.second << endl;cout << k.first << " " << k.second << endl;cout << s.first << " " << s.second << endl;return 0;
}

3.make_pair函数(函数模版)

传入key , value 生成 pair , 并返回pair

#include<iostream>
#include<vector>
#include<string>
#include<map>
#include<queue>
#include<utility>
using namespace std;
int main()
{pair<string, string> t = { "abc" , "def" };t = make_pair<string,string>("afad", "fasd");cout << t.first << " " << t.second << endl;return 0;
}

3.set

  1. set是按照某一次序存储元素的
  2. set是key值模型,但也存在value(并且value = key ),set中key(value)值不能修改
  3. 底层使用红黑树实现的

构造函数

1.迭代器区间构造

2.拷贝构造

#include<iostream>
#include<vector>
#include<string>
#include<map>
#include<set>
#include<queue>
#include<utility>
using namespace std;
int main()
{vector<string> ret = { "a" , "b" , "c" };set<string>  ans(ret.begin(), ret.end());set<string> k = ans;for (auto& e : ans)cout << e << endl;return 0;
}

find函数

给定一个key,如果set中存在,返回该节点的迭代器,不存在,返回set.end()

#include<iostream>
#include<vector>
#include<string>
#include<map>
#include<set>
#include<queue>
#include<utility>
using namespace std;
int main()
{vector<string> ret = { "a" , "b" , "c" };set<string>  ans(ret.begin(), ret.end());auto it = ans.find("a");if (it != ans.end())cout << *it << endl;elsecout << "不存在" << endl;return 0;
}

count函数:

给定一个key值 ,如果set中存在,返回1 , 不存在,返回0(与find函数相似)

int main()
{vector<string> ret = { "a" , "b" , "c" };set<string>  ans(ret.begin(), ret.end());int i = ans.count("a");if (i)cout << i << endl;else cout << i << endl;return 0;
}

insert函数


声明:pair<iterator, bool> insert(const value_type& val);

插入元素到 set 中。


如果插入成功,返回一个迭代器指向插入的位置和 true。


如果元素已经存在,返回一个迭代器指向已存在的元素和 false。


返回一个 pair 对象,包含插入的迭代器和插入是否成功的标志。

int main()
{vector<string> ret = { "a" , "b" , "c" };set<string>  ans(ret.begin(), ret.end());ans.insert({ "d" });return 0;
}

  1. 删除一个迭代器所指向的节点
  2. 删除某一特定的值
  3. 删除某一迭代区间(左闭右开)
#include<iostream>
#include<vector>
#include<string>
#include<map>
#include<set>
#include<queue>
#include<utility>
using namespace std;
int main()
{set<string> ret = { {"ab"} , {"cd"} , {"ef"} };ret.erase("ab");// 删除某一特定的值for (auto& e : ret)cout << e << endl;cout << endl;ret.insert({ "ab" });ret.erase(ret.begin());// 删除某一迭代器for (auto& e : ret)cout << e << endl;cout << endl;ret.insert({ "ab" });ret.insert({ "tt" });auto it = ret.find("tt");ret.erase(ret.begin(), it);for (auto& e : ret)cout << e << endl;return 0;
}

4.multiset

  1. multiset是按照特定顺序存储元素的容器,其中元素是可以重复的。
  2. 在multiset中,元素的value也会识别它(因为multiset中本身存储的就是<value, value>组成的键值对,因此value本身就是key,key就是value,类型为T). multiset元素的值不能在容器中进行修改(因为元素总是const的),但可以从容器中插入或删除。
  3. 在内部,multiset中的元素总是按照其内部比较规则(类型比较)所指示的特定严格弱排序准则进行排序。
  4. multiset容器通过key访问单个元素的速度通常比unordered_multiset容器慢,但当使用迭代器遍历时会得到一个有序序列。
  5. multiset底层结构为二叉搜索树(红黑树)

注意:

  1. multiset中再底层中存储的是<value, value>的键值对
  2. mtltiset的插入接口中只需要插入即可
  3. 与set的区别是,multiset中的元素可以重复,set是中value是唯一的
  4. 使用迭代器对multiset中的元素进行遍历,可以得到有序的序列
  5. multiset中的元素不能修改
  6. 在multiset中找某个元素,时间复杂度为O ( l o g 2 N ) 
  7. multiset的作用:可以对元素进行排序

multiset 是 C++ 标准库中的关联式容器之一,属于有序容器。与 set 不同的是,multiset 允许键值重复,即可以包含相同键值的多个元素。

允许重复键值: multiset 允许容器中存在相同的键值,因此可以包含多个相同键值的元素。

有序性: 与 set 类似,multiset 也维护元素的有序性,根据键值进行排序。

当需要允许键值重复,并且希望保持元素有序时,可以选择使用 multiset。

#include<iostream>
#include<vector>
#include<string>
#include<map>
#include<set>
#include<queue>
#include<utility>
using namespace std;
int main()
{vector<int> k = { 2,1,5,6,7,3,1,1,1,90 };multiset<int> ret(k.begin(), k.end());for (auto& e : ret)cout << e << " ";cout << endl;return 0;
}

5.map

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

5.1map 模板参数说明

  1. key: 键值对中key的类型
  2. T: 键值对中value的类型
  3. Compare: 比较器的类型,map中的元素是按照key来比较的,缺省情况下按照小于来比较,一般情况下(内置类型元素)该参数不需要传递,如果无法比较时(自定义类型),需要用户自己显式传递比较规则(一般情况下按照函数指针或者仿函数来传递)
  4. Alloc:通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标准库提供的空间配置器

构造函数

1.迭代器区间构造

2.拷贝构造

insert函数

void test()
{map<int,int> ret;ret.insert({1,1});ret.insert(make_pair(1,1));auto tmp = make_pair(1,1);ret.insert(tmp);
}

operator[]

返回的是关于value的引用

1.读取元素:当使用 [] 运算符时

  • 如果指定的键存在于 map 中,则返回与该键关联的值
  • 如果不存在,则会插入一个新的键值对,键为指定的键,值为默认构造的对应值类型的默认值,并返回该默认值的引用

2.插入元素:当使用 [] 运算符向 map 中插入元素时

  • 如果指定的键不存在,则会创建一个新的键值对,键为指定的键,值为指定的值,并返回该值的引用
  • 如果键已经存在,则直接返回对应的值的引用。
#include<iostream>
#include<map>
using namespace std;
int main()
{map<int, int> ret;vector<int> ans = { 1, 2, 3, 4, 5,6 ,6,7, };for (auto& e : ans){ret[e]++;// 插入pair}for (auto& e : ret){cout << e.first << " " << e.second << endl;}ret[1] = 10; // 修改pairreturn 0;
}

erase

第一种:删除 key 为某一个值的pair

#include<iostream>
#include<map>
using namespace std;
int main()
{map<int, int> ret;vector<int> ans = { 1, 2, 3, 4, 5,6 ,6,7, };for (auto& e : ans){ret[e]++;}for (auto& e : ret){cout << e.first << " " << e.second << endl;}ret.erase(1);cout << endl;for (auto& e : ret){cout << e.first << " " << e.second << endl;}return 0;
}

第二种:删除某一迭代区间(左闭右开)


#include<iostream>
#include<map>
using namespace std;
int main()
{map<int, int> ret;vector<int> ans = { 1, 2, 3, 4, 5,6 ,6,7, };for (auto& e : ans){ret[e]++;}for (auto& e : ret){cout << e.first << " " << e.second << endl;}auto p1 = ret.find(3);auto p2 = ret.find(6);cout << endl;ret.erase(p1, p2);for (auto& e : ret){cout << e.first << " " << e.second << endl;}return 0;
}

6.multimap

multimap的基本性质

  • multimap容器是和map容器相似的关联式容器,所谓“相似”,是指multimap容器具有和map容器相同的特性,即multimap容器也存储pair<const K, T>类型的键值对(其中K表示键的类型,T表示值的类型),其中各个键值对的键的值不能被修改;并且,该容器也会自行根据键的大小对所存储的所有键值对做排序操作。
  • multimap容器和map容器的区别在于,multimap容器中可以同时存储多个键相同的键值对。
  • multimap容器提供的成员方法,map容器都有提供,并且它们的用法是相同的。详细的用法请参照map的用法及实例详解。本文只是给出了所有在multimap中的成员函数及其实现功能,具体的实例及代码请参照map容器。
  • 实现multimap容器的类模板也定义在<map>头文件,并位于std命名空间中,故使用multimap容器前,应该引入头文件:#include<map>

构造函数

创建空的multimap

multimap<int,int> ret;

创建multimap并初始化(注意用{})

multimap<int, int> ret{ { 1,1 }, { 2,3 }, { 5,6 } };

拷贝构造

multimap<int,int> ans(ret);

迭代区间构造


#include<iostream>
#include<map>
#include<climits>
using namespace std;
int main()
{multimap<int, int> ret{ { 1,1 }, { 2,3 }, { 5,6 } };multimap<int, int> ans(++ret.begin(),ret.end());for (auto& e : ans)cout << e.first << " " << e.second << endl;return 0;
}

常见成员函数和使用方法:

注意multimap并没有重载operator[]

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

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

相关文章

极验4点选逆向 JS逆向分析 最新版验证码

目录 声明&#xff01; 一、请求流程分析 二、加密参数w与payload 三、参数w生成位置 四、结果展示&#xff1a; 原创文章&#xff0c;请勿转载&#xff01; 本文内容仅限于安全研究&#xff0c;不公开具体源码。维护网络安全&#xff0c;人人有责。 声明&#xff01; 本文章…

丢失的数字 ---- 位运算

题目链接 题目: 分析: 解法一: 哈希表解法二: 高斯求和解法三:位运算 异或运算根据运算的性质, 相同的两个a异或 0 以示例一为例: 数组中有0,1,3, 缺失的数字是2, 那么只要我们将数组与0,1,2,3 异或, 就会得到2 代码: class Solution {public int missingNumber(int[] num…

JCR一区级 | Matlab实现TCN-LSTM-MATT时间卷积长短期记忆神经网络多特征分类预测

JCR一区级 | Matlab实现TCN-LSTM-MATT时间卷积长短期记忆神经网络多特征分类预测 目录 JCR一区级 | Matlab实现TCN-LSTM-MATT时间卷积长短期记忆神经网络多特征分类预测分类效果基本介绍程序设计参考资料 分类效果 基本介绍 1.JCR一区级 | Matlab实现TCN-LSTM-MATT时间卷积长短…

图形学初识--屏幕空间变换

文章目录 前言正文为什么需要屏幕空间变换&#xff1f;什么是屏幕空间变换&#xff1f;屏幕空间变换矩阵如何推导&#xff1f;问题描述步骤描述 结尾&#xff1a;喜欢的小伙伴点点关注赞哦! 前言 前面章节主要讲解了视图变换和投影变换&#xff0c;此时距离在屏幕空间显示也就…

2024年6月1日 (周六) 叶子游戏新闻

Embracer探讨单机游戏大作涨价超过70美元的可能性在Embracer集团等待公布新公司名称的同时&#xff0c;他们对游戏大作的价格上涨做出了评论。几年来&#xff0c;游戏大作的价格已经达到了70美元的门槛。Embracer集团的CEO Lars Wingefors在采访中表示&#xff0c;电子游戏行业…

ch5链路层和局域网

回顾TCP/IP参考模型&#xff0c;明确链路层和物理层在整个模型中的地位&#xff0c;简要提出链路层要解决的问题是单段链路的数据传输&#xff0c;物理层解决的是数字信号与电气信号之间的相互转换。 链路层概述 节点&#xff1a;主机和路由器(包括网桥和交换机) 链路&#xf…

在table中获取每一行scope的值

目的 当前有一份如下数据需要展示在表格中&#xff0c;表格的页面元素套了一个折叠面板&#xff0c;需要循环page_elements中的数据展示出来 错误实践 将template放在了折叠面板中&#xff0c;获取到的scope是空数组 <el-table-column label"页面元素" show-o…

Qt for android 串口库使用

简介 由于Qt for android并没有提供android的串口执行方案&#xff0c;基于需要又懒得自己去造轮子&#xff0c; 使用开源的 usb-serial-for-android 库进行串口访问读写。 如果有自己的需要和库不满足的点&#xff0c;可以查看库的底层调用的Android相关API C/C 串口库 对应…

代码随想录算法训练营第三十五 | ● 860.柠檬水找零 ● 406.根据身高重建队列 ● 452. 用最少数量的箭引爆气球

860.柠檬水找零 讲解链接&#xff1a;https://programmercarl.com/0860.%E6%9F%A0%E6%AA%AC%E6%B0%B4%E6%89%BE%E9%9B%B6.html 本题只有5元10元20元&#xff0c;只需要考虑收到5、10、20这三种情况&#xff1b; 收到5元&#xff0c;五块的个数&#xff1b; 收到10&#xff0c;找…

易联众智能自动办理平台,AI赋能让数字政务服务“触手可及”

“城乡居民参保怎么办”“要去XX省工作了,帮我办理异地就医备案”……通过口语化的文字、语音提问,易联众智能自动办理平台的AI助理都可以准确理解对话,并依据政策文件给出详细回答,人机对话像聊天一样轻松。 近日,宁德市民王先生高兴地说:“过去办理医保业务不懂流程,容易走弯…

前端3剑客(第1篇)-初识HTML

100编程书屋_孔夫子旧书网 当今主流的技术中&#xff0c;可以分为前端和后端两个门类。 前端&#xff1a;简单的理解就是和用户打交道 后端&#xff1a;主要用于组织数据 而前端就Web开发方向来说&#xff0c; 分为三门语言&#xff0c; HTML、CSS、JavaScript 语言作用HT…

《已解决》F12显示已在程序中暂停

首先打开F12-->源代码 最后一步&#xff1a;

【linux】宝塔,首页挂载磁盘,显示使用情况

挂载前&#xff1a; 挂载后&#xff1a; 数据无价&#xff0c;建议&#xff1a;备份需要挂载的磁盘&#xff0c;或者使用新磁盘来进行操作。 1、下载自动挂载磁盘的脚本&#xff1a; wget -O auto_disk.sh http://download.bt.cn/tools/auto_disk.sh 2、给脚本添加执行权限&a…

IP 分片过程及偏移量计算

IP 报头中与分片相关的三个字段 1、 标识符&#xff08; ldentifier )&#xff1a;16 bit 该字段与 Flags 和 Fragment Offest 字段联合使用&#xff0c; 对较大的上层数据包进行分段&#xff08; fragment &#xff09; 操作。 路由器将一个包拆分后&#xff0c;所有拆分开的…

【linux】docker安装下载器:aria2、gopeed、thunder迅雷

一、aria2 1、下载aria2服务镜像 docker pull p3terx/aria2-pro 2、下载ariang页面服务 docker pull p3terx/ariang 3、启动aria2服务 docker run -d --name aria2 \ --restart unless-stopped \ --log-opt max-size1m \ -e PUID$UID \ -e PGID$GID \ -e UMASK_SET022 \ -…

MQTT之使用mosquitto

1、下载并安装mosquitto 参考&#xff1a;04 Windows下mosquitto安装_mosquitto-1.6.9-install-windows-x64 windowsserver系-CSDN博客 2、启动 2.1添加用户 .\mosquitto_passwd -c pwfile.example user1 报错信息如下&#xff1a; Error: Unable to open file C:\Program…

【SQL学习进阶】从入门到高级应用(一)

文章目录 ✨MySQL命令行基本命令✨数据库表的概述✨初始化测试数据✨熟悉测试数据 &#x1f308;你好呀&#xff01;我是 山顶风景独好 &#x1f495;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01; &#x1f495;希望您在这里可以感受到一份轻松愉快的氛围…

共计3万字!从零开始创建一个小规模的稳定扩散模型!

节前&#xff0c;我们星球组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学。 针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 合集&#x…

stack学习

std::stack 类是一种容器适配器&#xff0c;它给予程序员栈的功能——特别是 FILO&#xff08;先进后出&#xff09;数据结构。该类模板用处为底层容器的包装器——只提供特定函数集合。栈从被称作栈顶的容器尾部推弹元素。 operator 赋值给容器适配器 (公开成员函数) 元素访问…

JCR一区级 | Matlab实现TCN-BiGRU-MATT时间卷积双向门控循环单元多特征分类预测

JCR一区级 | Matlab实现TCN-BiGRU-MATT时间卷积双向门控循环单元多特征分类预测 目录 JCR一区级 | Matlab实现TCN-BiGRU-MATT时间卷积双向门控循环单元多特征分类预测分类效果基本介绍程序设计参考资料 分类效果 基本介绍 1.Matlab实现TCN-BiGRU-MATT时间卷积双向门控循环单元多…