C++:map和set的认识和简单使用/关联式容器

news2025/1/18 8:41:05

关联式容器

关联式容器即是用来存储数据的,并且存储的是<Key,Value>结构的键值对,在数据检索时效率比序列式容器高。

序列式容器也就是vector、list、queue等容器,因为其底层为线性序列的数据结构,里面存储的是元素本身。

键值对

用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息。比如,英汉翻译中,苹果对应着apple,香蕉对应着banana。

pair/make_pair

map和set底层实现原理都是二叉树,准确地来说,是红黑树。而map和set的区别就是,set没有键值对,只有一个value。而map则是拥有键值对,在底层的实现中,键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型value_type绑定在一起,为其取别名称为pair:

typedef pair<const key, T> value_type;

而pair是一个类,里面的成员分别是first和second,first表示的是第一个类型的变量,seconde表示第一个类型的变量。

通过pair来绑定键值对,比如pair<string,int>("str",1)。其中,pair<string,int>可以使用make_pair来替换,make_pair("str",1)。

其实make_pair就是对pair进行了封装。 

 make_pair返回的值,就是一个pair的对象。

树形结构的关联式容器

关联式容器有两种:一种是哈希结构的关联式容器,另一种是树形结构的关联式容器。树型结构的关联式容器主要有四种:map、set、multimap、multiset。这四种容器的共同点是:使用平衡搜索树(即红黑树)作为其底层结果,容器中的元素是一个有序的序列。

set容器

认识set

①set是按照一定次序存储元素的容器

②在set中,元素的key也标识它,并且每个key必须是唯一的。

③set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们

④set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则(set中的元素默认按照小于来比较)进行排序,即升序。

⑤set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对子集进行直接迭代。

⑥set在底层是用二叉搜索树(红黑树)实现的

⑦set中查找某个元素,时间复杂度为:long_2 N

⑧set中的元素不可以重复(因此可以使用set进行去重)

⑨使用set的迭代器遍历set中的元素,可以得到有序序列

⑩set中的元素不允许修改

使用set

set的模板参数列表:

T:set中元素的类型。Compare:set中元素默认按照小于来比较,less<T>。Alloc:et中元素空间的管理方式,使用STL提供的空间配置器管理

具体函数接口这里就不一一列出来了,要用的时候,一个优秀的程序员应该拥有查和阅读文档的能力。下方是文档链接:set的文档

下面是代码是使用例子:

#include<iostream>
#include<set>
using namespace std;


int main()
{
	//使用数组arr中的元素构造set
	int arr[] = { 2,3,5,6,1,8,7,4,9,2,0,3,0,1 };
	set<int> s(arr, arr + sizeof(arr) / sizeof(arr[0]));
	cout << s.size() << endl;

	//打印set中的元素
	for (auto& e : s)
	{
		cout << e << " ";
	}
	cout << endl;

	//set中值为3的元素出现的次数
	cout << s.count(3) << endl;

	cout << endl;

	//使用迭代器
	auto it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
	}
	cout << endl;

	//查找元素
	auto pos1 = s.find(3);                 //O(logN)
	auto pos2 = find(s.begin(), s.end(), 3);//O(N)

	//删除pos元素
	if (pos1 != s.end())
	{
		s.erase(pos1);
	}
	cout << s.erase(1);
	cout << s.erase(3);

	//对[)左闭右开的区间的元素进行删除
	set<int> myset;
	set<int>::iterator itlow, itup;

	//10 20 30 40 50 60 70 80 90 
	for (int i = 1; i < 10; ++i) myset.insert(i * 10);
	itlow = myset.lower_bound(25);
	itup = myset.upper_bound(65);
	//对[25,65)范围的数据全部删除
	myset.erase(itlow, itup);

	return 0;
}

multiset容器

multiset与set的区别就是,set去重,而multiset不去重。其它与set几乎一样,但multiset底层实际存储的是<int,int>键值对。

int main()
{
	int array[] = { 2, 1, 3, 9, 6, 0, 5, 8, 4, 7 };
	// 注意:multiset在底层实际存储的是<int, int>的键值对
	multiset<int> s(array, array + sizeof(array) / sizeof(array[0]));
	for (auto& e : s)
		cout << e << " ";
	cout << endl;
	return 0;
}

map容器

认识map

①map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元素

②在map中,键值key通常用于排序和唯一地标识元素,而值value中存储与此键值key关联的内容,key与value使用pair绑定起来。

③map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)。

④map支持下标访问符,即在[]中放入key,就可以找到与key对应的value。这个下标访问,是我们平常使用的随机访问有点不一样,下面将会对[]进行主要分析。

⑤map通常被实现为二叉搜索树(红黑树)

使用map

map的模板参数:

Key:键值对中key的类型。

T:键值对中的value的类型。

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

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

需要说明的接口:

operator[]

mapped_type& operator[] (const,key_type& k)返回去key对应的value

通过查文档我们发现,map中的operator[]传入的是key值,返回来的是key值对应的value的引用。需要注意的是,在元素访问时,有一个与operator[]类似的操作at()(该函数不常用)函数,都是通过key找到与key对应的value然后返回其引用,不同的是:当key值不存在时,operator[]用默认value与key构造键值对然后插入,返回改默认的value,而at()则是直接抛异常。

使用例子:

	//pair/make_pair
	map<string, string> dict;
	dict.insert(pair<string, string>("排序", "sort"));
	dict.insert(pair<string, string>("右边", "right"));
	dict.insert(pair<string, string>("左边", "left"));
	dict.insert(make_pair("字符串", "string"));

	//operator[]
	dict["迭代器"] = "iterator";
	dict["插入"];
	//修改
	dict.insert(pair<string, string>("左边", "xxx"));
	dict["插入"] = "insert";
	//查找
	cout << dict["左边"] << endl;

总结一下:

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

multimap容器

multimap和map的唯一不同就是:map中的key是唯一的,而multimap中key是可以重复的。

注意:

①multimap中的key是可以重复的。
②multimap中的元素默认将key按照小于来比较
③multimap中没有重载operator[]操作。因为一个key对应着多个value,不知道要找哪一个。
④使用时与map包含的头文件相同

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

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

相关文章

虹科案例 | 对症下药,零售行业BI解决方案及实操案例!

数据源多难以整合&#xff1f; 无法实时访问数据&#xff1f; 数据分析难、价值共享难&#xff1f; 面对大量的数据&#xff0c;企业愈发头疼&#xff0c;尤其是零售行业。虹科Domo商业智能分析工具“对症下药”&#xff0c;为零售企业海量数据问题提供解决方案。 一、零售行业…

如何使用CRM做好交付项目管理

在企业客户生命旅程中&#xff0c;项目实施期是最为关键的阶段之一。项目交付物是衡量实施过程质量的重要指标之一。项目交付物也是项目实施过程中体现项目成果的重要依据&#xff0c;项目交付物还是项目实施全生命周期过程管理的综合结晶&#xff0c;所以项目过程管理中项目交…

nslookup命令使用技巧

前言 nslookup是一个DNS查询工具&#xff0c;可以指定查询的类型&#xff0c;可以查到DNS记录的生存时间&#xff0c;还可以指定使用哪个DNS服务器进行解释。 一、缺省查询 不指定 dns-server&#xff0c;使用系统默认的 dns 服务器。 nslookup 域名 通过上述命令的执行结果…

设计「业务」与「技术」方案

三天研发&#xff0c;两天设计&#xff1b; 01【优先做设计方案】 职场中的那些魔幻操作&#xff0c;研发最烦的是哪个&#xff1f; 作为一个数年且资深的互联网普通开发&#xff0c;可以来说明一下为什么是&#xff1a;缺乏设计&#xff1b; 面对业务需求的时候&#xff0c…

使用Vuex实现商品列表的校验、添加、删除、统计

场景&#xff1a;使用Vuex实现一个商品列表的添加、删除以及利用Vuex中的getters属性计算商品列表的总数总价格 添加商品时判断当前商品列表中是否包含了相同的商品 添加商品时&#xff0c;对添加表单做了校验 Vuex的使用及原理已经在上篇文章中介绍过了 vue2.x中使用vuex_前端…

XLSX插件使用 — 导入导出(含中文表头)(React+Antd 对上传表格做数据格式验证)

需求说明 1.需要前端做数据导出&#xff08;非调用接口&#xff09; 2.需要对上传的表格数据做验证&#xff0c;不通过验证需要提示格式不正确&#xff0c;阻拦上传 技术栈介绍 ReactAntdesignXLSX js-xlsx 介绍 由SheetJS出品的js-xlsx是一款非常方便的只需要纯JS即可读取…

Kafka技术认知

文章目录概念理解名词解释基本架构工作流程Kafka的特性概念理解 Kafka是分布式的基于发布-订阅消息队列。是一个分布式、支持分区的、多副本的&#xff0c;基于 Zookeeper 协调的分布式消息中间件系统&#xff0c;它的最大的特性就是可以实时的处理大量数据以满足各种需求场景…

FISCO BCOS 搭建区块链,在SpringBoot中调用合约

一、搭建区块链 使用的是FISCO BCOS 和 WeBASE-Front来搭建区块链&#xff0c;详细教程&#xff1a; https://blog.csdn.net/yueyue763184/article/details/128924144?spm1001.2014.3001.5501 搭建好能达到下图效果即可&#xff1a; 二、部署智能合约与导出java文件、SDK证…

【C语言】程序环境和预处理

&#x1f307;个人主页&#xff1a;平凡的小苏 &#x1f4da;学习格言&#xff1a;别人可以拷贝我的模式&#xff0c;但不能拷贝我不断往前的激情 &#x1f6f8;C语言专栏&#xff1a;https://blog.csdn.net/vhhhbb/category_12174730.html 小苏希望大家能从这篇文章中收获到许…

决策树和期望货币价值

1、决策树和期望货币价值&#xff08;决策树、表&#xff09;---风险管理决策树分析是风险分析过程中的一项常用技术。某企业在项目风险分析过程中&#xff0c;采用了决策树分析方法&#xff0c;并计算出了EMV&#xff08;期望货币值&#xff09;。以下说法中&#xff0c;正确的…

使用 OpenAI 的 ChatGPT 提高开发人员的工作效率

&#x1f482; 个人网站:【海拥】【摸鱼游戏】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 想寻找共同学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 介绍 作为一名开发人…

第十天栈和队列

栈和队列的原理大家应该很熟悉了&#xff0c;队列是先进先出&#xff0c;栈是先进后出。首先大家要知道 栈和队列是STL&#xff08;C标准库&#xff09;里面的两个数据结构。接下来介绍的栈和队列也是SGI STL里面的数据结构&#xff0c; 知道了使用版本&#xff0c;才知道对应的…

雅思经验(6)

反正我是希望遇到的雅思听力section 4.里面填空的地方多一些&#xff0c;之后单选的部分少一些。练了一下剑9 test3 的section 4&#xff0c;感觉还是不难的&#xff0c;都是在复现&#xff0c;而且绕的弯子也不是很多。本次考试的目标就是先弄一个六分&#xff0c;也就是说&am…

构建Jenkins 2.340持续集成环境

一、前言 本文学习自&#xff1a;2022版Jenkins教程&#xff08;从配置到实战) 如有不妥&#xff0c;欢迎指正 二、构建资料 已经包括了本文档使用的所有所需的安装包 三、安装docker 1、解压docker docker-20.10.10.tgz2、复制文件 cp docker/* /usr/bin/3、编写启动文…

第三节 第一个内核模块

hellomodule 实验 实验说明 硬件介绍 本节实验使用到STM32MP157 开发板 实验代码讲解 本章的示例代码目录为&#xff1a;linux_driver/module/hellomodule 从前面我们已经知道了内核模块的工作原理&#xff0c;这一小节就开始写代码了&#xff0c;跟hello world 一样&…

经典文献阅读之--PLC-LiSLAM(面,线圆柱SLAM)

0. 简介 对于激光SLAM来说&#xff0c;现在越来越多的算法不仅仅局限于点线等简答特征的场景了&#xff0c;文章《PLC-LiSLAM: LiDAR SLAM With Planes, Lines,and Cylinders》说到&#xff0c;平面、线段与圆柱体广泛存在于人造环境中。为此作者提出了一个使用这些landmark的…

kafka集群搭建及问题

一、zookeeper集群搭建 1、创建文件夹 cd /home mkdir zookeeper 2、下载 cd zookeeper wget https://downloads.apache.org/zookeeper/zookeeper-3.8.0/apache-zookeeper-3.8.0-bin.tar.gz 解压到当前文件夹 tar -zxvf apache-zookeeper-3.8.0-bin.tar.gz 文件夹重命…

icomoon字体图标的使用

很久之前就学习过iconfont图标的使用&#xff0c;今天又遇到一个用icomoon字体图标写的案例&#xff0c;于是详细学习了一下&#xff0c;现整理如下。 一、下载 1.网址&#xff1a; https://icomoon.io/#home 2.点击IcoMoon App。 3.点击 https://icomoon.io/app 4.进入IcoM…

每天10个前端小知识 【Day 10】

前端面试基础知识题 1. es5 中的类和es6中的class有什么区别&#xff1f; 在es5中主要是通过构造函数方式和原型方式来定义一个类&#xff0c;在es6中我们可以通过class来定义类。 class类必须new调用&#xff0c;不能直接执行。 class类执行的话会报错&#xff0c;而es5中…

【PyTorch】教程:Transfer learning

Transfer learning 实际工作中&#xff0c;只有很少的人从头开始训练 CNN&#xff0c;因为很难获得大量的样本。一般情况下&#xff0c;会通过调用预训练模型&#xff0c;例如 ConvNet 在 ImageNet&#xff08;1.2 M 图像 1000 个类别&#xff09;,可以用 ConvNet 初始化&#…