十八、map和set

news2025/1/12 23:17:35

文章目录

  • 一、关联式容器
    • (一)序列式容器:
    • (二)关联式容器:
  • 二、树形结构与哈希结构
    • (一)树型结构
    • (二)哈希结构
  • 三、键值对
  • 四、set
  • 五、multiset
  • 六、map
    • (一)[ ] 运算符重载
    • (二)统计次数的方式
    • (三)统计次数+排序
  • 七、multimap

一、关联式容器

(一)序列式容器:

序列式容器里面存储的是元素本身,其底层为线性序列的数据结构。比如:vector,list,deque,forward_list(C++11)等。

(二)关联式容器:

关联式容器里面存储的是<key, value>结构的键值对,在数据检索时比序列式容器效率更高。比如:set、map、unordered_set、unordered_map等。

注意:C++STL当中的stack、queue和priority_queue属于容器适配器,它们默认使用的基础容器分别是deque、deque和vector。

二、树形结构与哈希结构

根据应用场景的不同,C++STL总共实现了两种不同结构的关联式容器:
在这里插入图片描述

(一)树型结构

树型结构容器中的元素是一个有序的序列,而哈希结构容器中的元素是一个无序的序列。

(二)哈希结构

三、键值对

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

比如我们若是要建立一个英译汉的字典,那么该字典中的英文单词与其对应的中文含义就是一一对应的关系,即通过单词可以找到与其对应的中文含义。

--在SGI-STL中关于键值对的定义如下:
template <class T1, class T2>
struct pair
{
	typedef T1 first_type;
	typedef T2 second_type;
	T1 first;
	T2 second;
	pair() : first(T1()), second(T2())
	{}
	pair(const T1& a, const T2& b) : first(a), second(b)
	{}
};

四、set

  • set是按照一定次序存储元素的容器,使用set的迭代器遍历set中的元素,可以得到有序序列。
  • set当中存储元素的value都是唯一的,不可以重复,因此可以使用set进行去重。
  • 与map/multimap不同,map/multimap中存储的是真正的键值对<key, value>,set中只放value,但在底层实际存放的是由<value, value>构成的键值对,因此在set容器中插入元素时,只需要插入value即可,不需要构造键值对。
  • set中的元素不能被修改,因为set在底层是用二叉搜索树来实现的,若是对二叉搜索树当中某个结点的值进行了修改,那么这棵树将不再是二叉搜索树。
  • 在内部,set中的元素总是按照其内部比较对象所指示的特定严格弱排序准则进行排序。当不传入内部比较对象时,set中的元素默认按照小于来比较。
  • set容器通过key访问单个元素的速度通常比unordered_set容器慢,但set容器允许根据顺序对元素进行直接迭代。
  • set容器通过key访问单个元素的速度通常比unordered_set容器慢,但set容器允许根据顺序对元素进行直接迭代。

五、multiset

  • multiset容器与set容器的底层实现一样,都是平衡搜索树(红黑树),其次,multiset容器和set容器所提供的成员函数的接口都是基本一致的
  • multiset容器和set容器的唯一区别就是,multiset允许键值冗余,即multiset容器当中存储的元素是可以重复的

六、map

  • map是关联式容器,它按照特定的次序(按照key来比较)存储键值key和值value组成的元素,使用map的迭代器遍历map中的元素,可以得到有序序列。
  • 在map中,键值key通常用于排序和唯一地标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型value_type绑定在一起,并取别名为pair。
  • map容器中元素的键值key不能被修改,但是元素的值value可以被修改,因为map底层的二叉搜索树是根据每个元素的键值key进行构建的,而不是值value。
  • 在内部,map中的元素总是按照键值key进行比较排序的。当不传入内部比较对象时,map中元素的键值key默认按照小于来比较。
  • map容器通过键值key访问单个元素的速度通常比unordered_map容器慢,但map容器允许根据顺序对元素进行直接迭代。
  • map容器支持下标访问符,即在[]中放入key,就可以找到与key对应的value。
  • map在底层是用平衡搜索树(红黑树)实现的,所以在map当中查找某个元素的时间复杂度为logN。

(一)[ ] 运算符重载

mapped_type& operator[] (const key_type& k);
(*((this->insert(make_pair(k, mapped_type()))).first)).second

实际上[ ]运算符重载实现的逻辑实际上就是以下三个步骤:

  • 调用insert函数插入键值对。
  • 拿出从insert函数获取到的迭代器。
  • 拿出从insert函数获取到的迭代器。
mapped_type& operator[] (const key_type& k)
{
	//1、调用insert函数插入键值对
	pair<iterator, bool> ret = insert(make_pair(k, mapped_type()));
 
	//2、拿出从insert函数获取到的迭代器
	iterator it = ret.first;
 
	//3、返回该迭代器位置元素的值value
	return it->second;
}

如果k不在map中,则先插入键值对<k, V()>,然后返回该键值对中V对象的引用。
如果k已经在map中,则返回键值为k的元素对应的V对象的引用。
在这里插入图片描述

(二)统计次数的方式

	// 1、统计次数 
	string arr[] = { "香蕉", "苹果", "香蕉", "榴莲", "草莓", "苹果", "香蕉", "苹果","西瓜","西瓜", "香蕉", "草莓", "西瓜" };
 
	 //统计次数的方式1:
	map<string, int> countMap;
	for (const auto& str : arr)
	{
		// 思路:第一次出现,插入<str, 1>, 后续再出现就++次数ret->second
		map<string, int>::iterator ret = countMap.find(str);
		if (ret != countMap.end())
		{
			ret->second++;
		}
		else
		{
			countMap.insert(make_pair(str, 1));
		}
	}
 
	 //统计次数的方式2: 
	map<string, int> countMap;
	for (const auto& str : arr)
	{
		// 先插入,如果str已经在map中,insert会返回str所在节点的迭代器,我们++次数即可
		//pair<map<string, int>::iterator, bool>  ret = countMap.insert(make_pair(str, 1));
		auto ret = countMap.insert(make_pair(str, 1));
		if (ret.second == false)
		{
			ret.first->second++;
		}
	}
 
	// 统计次数方式3:
	map<string, int> countMap;
	for (const auto& str : arr)
	{
		countMap[str]++;
	}
 
	for (const auto& e : countMap)
	{
		cout << e.first << ":" << e.second << endl;
	}

(三)统计次数+排序

struct MapItCompare
{
	bool operator()(map<string, int>::iterator x, map<string, int>::iterator y)
	{
		return x->second < y->second;
	}
};
 
 
	// 一、统计次数  二、找出大家最喜欢(出现次数最多)的三种水果
	string arr[] = { "香蕉", "苹果", "香蕉", "榴莲", "草莓", "苹果", "香蕉", "苹果", "西瓜", "西瓜", "香蕉", "草莓", "西瓜" };
	map<string, int> countMap;
	for (const auto& str : arr)
	{
		countMap[str]++;
	}
 
	// 1. 对所有水果次数排序的思路
	//vector<pair<string, int>> v;
	vector<map<string, int>::iterator> v;
	map<string, int>::iterator countMapIt = countMap.begin();
	while (countMapIt != countMap.end())
	{
		v.push_back(countMapIt);
		++countMapIt;
	}
	sort(v.begin(), v.end(), MapItCompare());//自定义排序方式
 
	// 2. 利用map排序  -- 拷贝pair数据
	//map<int, string> sortMap;
	map<int, string, greater<int>> sortMap;
	for (auto e : countMap)
	{
		sortMap.insert(make_pair(e.second, e.first));
	}
 
	// 3. 利用set排序  --不拷贝pair数据
	set<map<string, int>::iterator, MapItCompare> sortSet;
	countMapIt = countMap.begin();
	while (countMapIt != countMap.end())
	{
		sortSet.insert(countMapIt);
		++countMapIt;
	}
     
    //4.优先级队列
	typedef map<string, int>::iterator M_IT;
	priority_queue<M_IT, vector<M_IT>, MapItCompare> pq;
	countMapIt = countMap.begin();
	while (countMapIt != countMap.end())
	{
		pq.push(countMapIt);
		++countMapIt;
	}
}
 

七、multimap

  • multimap容器与map容器的底层实现一样,也都是平衡搜索树(红黑树),其次,multimap容器和map容器所提供的成员函数的接口都是基本一致的
  • multimap容器和map容器的区别与multiset容器和set容器的区别一样,multimap允许键值冗余,即multimap容器当中存储的元素是可以重复的。
  • 由于multimap容器允许键值冗余,调用[ ]运算符重载函数时,应该返回键值为key的哪一个元素的value的引用存在歧义,因此在multimap容器当中没有实现[ ]运算符重载函数。

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

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

相关文章

有没有一种支持对象建模、数据库建模和低代码能力的工具,用来解放程序员生产力呢?

1. 简介 作为一个程序员&#xff0c;很多时候在面对项目开发工期短、任务重、功能复杂、压力大&#xff0c;同时还得迎合领导或者甲方的要求提供研发设计文档时&#xff0c;往往很苦恼&#xff0c;因为随着软件项目的迭代&#xff0c;很难保持输出与代码一致的数据模型和架构模…

Configuring MySQL for a SSD based SAN

Configuring MySQL for a SSD based SAN (Doc ID 2673662.1)正在上传…重新上传取消To Bottom In this Document APPLIES TO: MySQL Server - Version 5.6 and later Information in this document applies to any platform. GOAL Considering a Virtualized environment wit…

chatgpt赋能Python-python_ip归属地

Python IP归属地查询 在网络安全领域&#xff0c;IP地址归属地查询是一项非常重要的任务。很多时候我们需要知道某个IP地址的归属地以解决一些安全问题。Python语言在这方面也发挥了巨大的作用&#xff0c;有各种成熟的IP地址归属地查询库。在本文中&#xff0c;我们将介绍如何…

CMOS摄像头驱动分析-i2c驱动

CMOS摄像头驱动分析-i2c驱动 文章目录 CMOS摄像头驱动分析-i2c驱动设备树内容module_i2c_driver宏分析ov2640_i2c_driverov2640_probe 设备树内容 ov2640: camera0x30 {compatible "ovti,ov2640";reg <0x30>;status "okay";pinctrl-names "…

三、Mybatis从入门到入土

一、什么是Mybatis 1&#xff09;MyBatis 是一款优秀的持久层&#xff08;DAO层&#xff09;框架 2&#xff09;MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的过程 3&#xff09;MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息&#xff0c;将…

程序员做爬虫有哪些痛点

很多网站会设置反爬虫机制&#xff0c;如验证码、IP封禁、请求频率限制等&#xff0c;这些机制会增加爬虫的难度。 程序员做爬虫时&#xff0c;可能会遇到以下难点&#xff1a; 1、反爬虫机制 许多网站会设置反爬虫机制&#xff0c;如验证码、IP封禁、请求频率限制等&#x…

ICV: ADAS SoC市场规模将在2024年迎来较大突破

随着先进驾驶辅助系统&#xff08;ADAS&#xff09;的出现和对于自动驾驶的追求&#xff0c;汽车行业正在经历快速转型。这些技术进步的核心是ADAS SoC&#xff0c;它是实现多个功能集成于单一平台的关键组件。ADAS SoC已经成为智能汽车的重要驱动因素&#xff0c;彻底改变了安…

Linkage Mapper Toolkit中的 Barrier Mapper 功能解析(含实际案例分析)

✅创作者:陈书予 🎉个人主页:陈书予的个人主页 🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区 🌟专栏地址: Linkage Mapper解密数字世界链接 文章目录 🎉引言🌟博客介绍🌟Linkage Mapper 工具和 ArcGIS 简介🎉Barrier Mapper 和 ArcGIS 的集成</

python内置模块之logging

文章目录 1 开始使用 logging 1.1 第一个程序1.2 日志级别1.3 输出格式 2 输出日志到文件 2.1 使用 basicConfig 配置文件路径2.2 logging 模块化设计2.3 自动分割日志文件 最近因为一个小需求&#xff0c;需要保存日志到文件中。因为平时调试都只是用print&#xff0c;当不…

Cesium教程(五):加载自定义地形数据

目录 1、准备数据 2、转化数据 3、发布数据 4、加载数据 5、数据下载地址 1、准备数据 可以从NASA网站免费下载30m空间分辨率高程模型数据 在地图上选择区域之后&#xff0c;点击左侧对应区域下载即可&#xff1a; 也可以在地理空间数据云上下载所需要的地区数据地理空间数…

Zeebe系列(1)-- Zeebe官方管理台使用

Zeebe管理台创建 注册zeebe账号&#xff0c;可以获得30天的免费试用期。可以在官方提供的管理台页面进行zeebe集群的创建等操作。 Accounts | Sign Up - Camunda Zeebe管理台是进行流程管理的界面&#xff0c;主要包括5个组件。 Console Console&#xff1a;Zeebe的控制台&…

Java高并发核心编程—内置锁原理篇

注&#xff1a;本笔记是阅读《Java高并发核心编程卷2》整理的笔记&#xff01; 导致并发修改的原因 例如Java中的i等指令并非是原子操作&#xff0c;而是三条指令的集合&#xff1a;“内存取值”、“寄存器增加1”、“存值到内存” 。 因此&#xff0c;如果是多线程并发使用C…

PHP操作宝塔面板Api,宝塔服务器搭建,API接口使用教程

最近两个月都在写Bty项目&#xff0c;所以收集了很多很多宝塔常用到的一些Api接口&#xff0c;官方文档虽然写了一点&#xff0c;但是始终是不怎么全的&#xff0c;下面我们来看看宝塔面板的接口如何抓取 接口抓取 1、登录宝塔面板 2、找到自己想要的功能 3、f12打开审查元素&a…

韵达转债上市价格预测

韵达转债 基本信息 转债名称&#xff1a;韵达转债&#xff0c;评级&#xff1a;AA&#xff0c;发行规模&#xff1a;24.5亿元。 正股名称&#xff1a;韵达股份&#xff0c;今日收盘价&#xff1a;12.23元&#xff0c;转股价格&#xff1a;12.15元。 当前转股价值 转债面值 / 转…

vue关于静态路由和动态路由:

这篇文章写得超详细&#xff01;&#xff01;&#xff01; &#x1f449;vue实现动态路由一步到位_vue动态路由怎么实现_ds_surk的博客-CSDN博客 目录 静态路由的配置&#xff1a; 步骤&#xff1a; 动态路由的配置&#xff1a; 步骤&#xff1a; 代码实现&#xff1a; …

网易云音乐开发--search模块基本功能实现(除历史记录模块)

search头部搭建 老样子搭建一个search搜索页面 还有一块没有实现&#xff0c;那就是让输入框默认的文本变换颜色 微信小程序: input输入框placeholder样式的修改_微信小程序placeholder样式_酷伊奥的博客-CSDN博客 百度搜索了一下&#xff0c;找到了这个大佬的解决方案。很nic…

ICV:中国的数字经济与5G市场研究报告

近日&#xff0c;专注于前沿科技领域的国际咨询机构ICV发布了《中国的数字经济与5G市场研究报告》。报告指出&#xff0c;随着5G商用的发展&#xff0c;5G对经济社会的影响逐步显现&#xff0c;其影响突出体现在对数字产业发展的带动上。随着5G应用的不断创新与扩散&#xff0c…

chrome插件打包之后,显示此扩展程序可能已损坏

每日鸡汤&#xff0c;每个你想要学习的瞬间都是未来的你向自己求救 问题是这样的&#xff0c;我们有一个chrome插件的项目&#xff0c;但是我也没有参与开发&#xff0c;可以说此前对chrome插件一窍不通。但是今天呢&#xff0c;有个bug&#xff0c;要我改&#xff0c;我就拉一…

基于Java+SpringBoot+Vue的校园交友网站的设计与实现

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架下…

为什么x86架构一个字节是8个bit

探究计算机存储的历史&#xff1a;为什么x86架构下一个字节是8个bit 原文链接&#xff1a;Some possible reasons for 8-bit bytes About author I’m a software developer. I live in Montreal. I sometimes give talks. Most of my income comes from my programming zines…