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.mzph.cn/news/846006.shtml

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

相关文章

力扣--双指针15.三数之和

详细思路 排序数组&#xff1a;首先对数组 nums 进行排序&#xff0c;目的是为了方便后续使用双指针查找和避免重复结果。遍历数组&#xff1a;使用一个 for 循环从头遍历到倒数第三个元素。i 表示当前固定的元素。 跳过重复元素&#xff1a;如果当前元素 nums[i] 与前一个元素…

SpringBoot项目实现自定义注解方式的接口限流

一&#xff0c;实现原理 该限流方式使用的是令牌桶算法&#xff0c;令牌桶算法是基于漏桶算法的一种改进&#xff0c;主要在于令牌桶算法能够在限制服务调用的平均速率的同时&#xff0c;还能够允许一定程度内的突发调用。 系统以固定的速率向桶中添加令牌当有请求到来时&#…

张大哥笔记:你卖什么,就反着来卖

普通人打工的一生&#xff0c;就是努力工作&#xff0c;买房&#xff0c;买车&#xff0c;送孩子上好的学校&#xff0c;为了孩子不要输在起跑线上&#xff0c;拼命报各种补习班等&#xff0c;这些都是普通人认为的主流价值观文化&#xff0c;也造就了一批批的赚钱机器&#xf…

带DSP音效处理D类数字功放TAS5805M中文资料

国产替代D类数字功放中文资料访问下方链接 ACM8628 241W立体声182W单通道数字功放中文寄存器表 内置DSP多种音频处理效果ACM8628M-241W立体声或182W单通道数字功放 1 特性 具有增强处理能力和低功率损耗的 TAS5805M 23W、无电感器、数字输入、立体声、闭环 D 类音频放大器 …

华为设备配置静态路由和默认路由

华为设备配置静态路由和默认路由 理论部分知识&#xff1a; 路由分为两个大类&#xff1a;静态路由-----动态路由 静态路由&#xff1a;手工指定&#xff0c;适用于小规模的网络应用场景&#xff0c;如果网络规模变大&#xff0c;这样的方式非常不适合而且容易出错。 语法&…

Java之IO流

一、引言 &#xff08;1&#xff09;解释&#xff1a; i&#xff1a;input &#xff08;输入&#xff09; o&#xff1a;output &#xff08;输出&#xff09; &#xff08;2&#xff09;图解 注意&#xff1a; 1、Xxx 这个程序一旦在桌面关闭掉了&#xff0c;也就是运行完…

动态路由OSPF单区域和多区域配置实验

动态路由OSPF的配置 OSPF分类两种情况&#xff1a;单区域 多区域路由 OSPF单区域路由配置 OSPF&#xff1a;开放最短路径优先的路由协议。属于大型动态路由协议&#xff0c;适用于中大型的园区网。 网络拓扑&#xff1a; 配置步骤&#xff1a; 1.完成基本配置&#xff08;略&…

能耗监测系统在上海交通大学闵行校区理科实验楼群的设计与应用

引言 建筑能耗系统&#xff0c;除了基本的电力参数监测、配电系统的运行状况&#xff0c;更加关注能耗的去向。除了常规的园区楼层出线电能计量&#xff0c;还会涉及水&#xff0c;气等能耗计量。 针对上海交通大学闵行校区理科实验楼群能耗监测系统的具体要求&#xff0c;以…

依赖管理包介绍

文章目录 1. 概念介绍2. 思路与方法2.1 实现思路2.2 相关组件 3. 示例代码4. 内容总结 我们在上一章回中介绍了"使用get进行依赖管理"相关的内容&#xff0c;本章回中将介绍如何使用get进行状态管理一.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 …

C语言:如何在微软VS环境下使用C库?

技术答疑流程 扫描二维码&#xff0c;添加个人微信&#xff1b;支付一半费用&#xff0c;获取答案&#xff1b;如果满意&#xff0c;则支付另一半费用&#xff1b; 知识点费用&#xff1a;10元 项目费用&#xff1a;如果有项目任务外包需求&#xff0c;可以微信私聊

IP路由策略1

控制层面:路由协议传递路由信息的流量--对应的方向 数据层面:设备间具体访问时请求的流量--对应方向 控制层面方向与数据层面方向一定相反 在控制层面流量进或出的接口上&#xff0c;抓取流量后&#xff0c;修改其中参数或删除该信息&#xff0c;最终起到影响路由器路由表的生…

「Django秘境探险:揭开Web开发的神秘面纱」

大家好&#xff0c;我是阿佑&#xff0c;今天将和大家一块学习到如何利用Django框架的高级特性&#xff0c;构建出既快速又安全的Web应用。我们将一起破解Django的内部机制&#xff0c;掌握从数据模型到模板设计的每一个环节。准备好了吗&#xff1f;Let’s go &#xff01; 文…

“手撕”链表的九道OJ习题

目录 1. 第一题 2. 第二题 3. 第三题 4. 第四题 5. 第五题 6. 第六题 7. 第七题 8. 第八题 9. 第九题 1. 第一题 删除链表中等于给定值 val 的所有节点。OJ链接 思路如下&#xff1a; 相当于链表的removeAll();制定prev和cur&#xff0c;prev记录前一个节点&#xff…

Windows11 wsl2编译Android14 使用ASfP Debug windows上启动的模拟器

wsl2的安装和配置 安装&#xff1a; 直接百度搜索最新的wsl2安装教程即可&#xff0c;官网&#xff1a;https://learn.microsoft.com/zh-cn/windows/wsl/install 1. 启用适用于 Linux 的 Windows 子系统(以管理员身份打开 PowerShell 并运行) Enable-WindowsOptionalFeature…

8-Django项目--登录及权限

目录 templates/login/login.html templates/login/404.html views/login.py utils/pwd_data.py auth.py settings.py 登录及权限 登录 views.py 中间件 auth.py templates/login/login.html {% load static %} <!DOCTYPE html> <html lang"en"&g…

Linux系统编程——动静态库

目录 一&#xff0c;关于动静态库 1.1 什么是库&#xff1f; 1.2 认识动静态库 1.3 动静态库特征 二&#xff0c;静态库 2.1 制作静态库 2.2 使用静态库 三&#xff0c;动态库 3.1 制作动态库 3.2 使用动态库一些问题 3.3 正确使用动态库三种方法 3.3.1 方法一&…

什么是BFC?

1、BFC&#xff1a;又叫块级格式化上下文&#xff08;block formatting context&#xff09;&#xff0c;就是页面上一个隔离的独立容器&#xff0c;容器里面的子元素不会影响到外面的元素。 2、BFC的原则&#xff1a;如果一个元素具有BFC&#xff0c;那么内部元素再怎么弄&am…

QuillEditor富文本结合vue3使用,可单独抽离成组件,富文本的内容可自定义

实现效果&#xff1a; 上方的粗体、斜体、字号、字体等各种信息支持自定义配置。 实现方式&#xff1a; 下面的介绍为分步骤的详细介绍&#xff0c;完整版纯享代码可参考这篇博客富文本QuillEditorvue3组件代码纯享版-CSDN博客 1.新建一个新文件--子组件&#xff0c;如命名为…

git应用最佳实践

插&#xff1a; AI时代&#xff0c;程序员或多或少要了解些人工智能&#xff0c;前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家(前言 – 人工智能教程 ) 坚持不懈&#xff0c;越努力越幸运&#xff0c;大家…