C++ —— map系列的使用

目录

1. map和multimap参考文档

2. map类的介绍

3. pair

4. map的增删查

4.1 插入 

 4.2 删除

 4.3 查找

5. map的数据修改

6. map的operator[]

7. multimap和map的差异


1. map和multimap参考文档

- C++ Referenceicon-default.png?t=O83Ahttps://legacy.cplusplus.com/reference/map/


2. map类的介绍

map可以对两个无关的值建立关系 

map的声明如下,Key就是map底层关键字的类型,T是map底层value的类型,set默认要求Key⽀持⼩于⽐较,如果不⽀持或者需要的话可以⾃⾏实现仿函数传给第⼆个模版参数

     

map底层存储数据的内存是从空间配置器申请的。⼀般情况下,我们都不需要传后两个模版参数

    

map底层是⽤红⿊树实现,增删查改效率是 O(logN) ,迭代器遍历是⾛的中序,所以是按key有序顺序遍历的

 map的三种构造

 

//1.显式实例化直接构造 
//map
int main()
{
	//显式定义
	map<string, string> dict;
	pair<string, string> key("first", "第一个");
	dict.insert(key);

	return 0;
}

//2.匿名对象构造
//map
int main()
{
	//显式定义
	map<string, string> dict;
	pair<string, string> key("first", "第一个");
	dict.insert(key);

	//匿名对象
	dict.insert(pair<string, string>("second", "第二个"));

	return 0;
}

//3. 函数模版构造
//map
int main()
{
	//显式定义
	map<string, string> dict;
	pair<string, string> key("first", "第一个");
	dict.insert(key);

	//匿名对象
	dict.insert(pair<string, string>("second", "第二个"));

	//make_pair函数模版直接插入
	dict.insert(make_pair("sort", "排序"));

	return 0;
}

map的多参数类型转换

//map
int main()
{
	//显式定义
	map<string, string> dict;
	pair<string, string> key("first", "第一个");
	dict.insert(key);

	//匿名对象
	dict.insert(pair<string, string>("second", "第二个"));

	//make_pair函数模版直接插入
	dict.insert(make_pair("sort", "排序"));

	//C++11支持多参数类型转换
	dict.insert({ "hello","泥嚎" });
	//key相同的情况下,value不相等不会更新,而且key不可以被修改而value可以
	dict.insert({ "hello","泥嚎xixixixixi" });

	//遍历,这里需要显式打印key与value,因为他们是公有的
	//map<string, string>::iterator it = dict.begin();
	auto it = dict.begin();
	while (it != dict.end())
	{
		//使用.访问
		//cout << (*it).first << ":" << (*it).second << endl;

		//使用->访问结构体,这里实际上就是重载了一个->
		//cout << it.operator->()->first << ":" << it.operator->()->second << endl;
		cout << it->first << ":" << it->second << endl;
		++it;
	}

	return 0;
}

 

补充一下:

1.在map中有一个pair存储key与value,后面我们使用的first就是key,second就是value

    

2.当新插入一个数据与原来某个数据相同时,如果key相同value不同的情况下,该数据不会更新,且key不可以被修改而value可以被修改

     

3.通常使用迭代器遍历map时需要显式的使用.或者->访问pair中的first与second,不能直接解引用

3. pair

map底层的红⿊树节点中的数据,使⽤pair<Key, T>存储键值对数据

 pair的参考文档:

pair - C++ Referenceicon-default.png?t=O83Ahttps://legacy.cplusplus.com/reference/utility/pair/?kw=pair  

typedef pair<const Key, T> value_type;
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)
   {}
 
   template<class U, class V> 
   pair (const pair<U,V>& pr): first(pr.first), second(pr.second)
   {}
};

template <class T1,class T2>
inline pair<T1,T2> make_pair (T1 x, T2 y)
{
 return ( pair<T1,T2>(x,y) );
}
 


4. map的增删查

map的增删查关注以下⼏个接⼝即可:

    
map增接⼝,插⼊的pair键值对数据,跟set所有不同,但是查和删的接⼝只⽤关键字key跟set是完全类似的,不过find返回iterator,不仅仅可以确认key在不在,还找到key映射的value,同时通过迭代还可以修改value

4.1 插入 

insert插⼊⼀个pair<key, T>对象

    
1、如果key已经在map中,插⼊失败,则返回⼀个pair<iterator,bool>对象,返回pair对象
first是key所在结点的迭代器,second是false

    
2、如果key不在在map中,插⼊成功,则返回⼀个pair<iterator,bool>对象,返回pair对象
first是新插⼊key所在结点的迭代器,second是true

也就是说⽆论插⼊成功还是失败,返回pair<iterator,bool>对象的first都会指向key所在的迭
代器那么也就意味着insert插⼊失败时充当了查找的功能,正是因为这⼀点,insert可以⽤来实现operator[]

     
需要注意的是这⾥有两个pair,不要混淆了,⼀个是map底层红⿊树节点中存的pair<key, T>,另⼀个是insert返回值pair<iterator,bool> 

如果插入成功就会返回pair<插入后的key的迭代器,true>,插入失败就返回pair<原来就存在相同key的迭代器,false>

//单个数据插⼊,如果已经key存在则插⼊失败,key存在相等value不相等也会插⼊失败 
pair<iterator, bool> insert(const value_type& val);

//列表插⼊,已经在容器中存在的值不会插⼊ 
void insert(initializer_list<value_type> il);

//迭代器区间插⼊,已经在容器中存在的值不会插⼊ 
template <class InputIterator>
void insert(InputIterator first, InputIterator last);
//插入
int main()
{
	map<int, string> mymap;
	//1.单个数据插⼊,如果已经key存在则插⼊失败,key存在相等value不相等也会插⼊失败 
    //pair<iterator, bool> insert(const value_type& val);
	mymap.insert({ 1, "first" });
	mymap.insert({ 1,"first_change" });
	auto it = mymap.begin();
	while (it != mymap.end())
	{
		cout << it->first << ":" << it->second << endl;
		it++;
	}
 
	return 0;
}

 4.2 删除

// 删除⼀个迭代器位置的值 
iterator erase (const_iterator position);

// 删除k,k存在返回0,存在返回1 
size_type erase (const key_type& k);

// 删除⼀段迭代器区间的值 
iterator erase (const_iterator first, const_iterator last);
//删除
int main()
{
	map<int, string> mymap;
	mymap.insert({ 1, "first" });
	mymap.insert({ 2,"second" });
	mymap.insert({ 3,"three" });
	mymap.insert({ 4,"four" });
	mymap.insert({ 5,"five" });
	auto it1 = mymap.begin();
	while (it1 != mymap.end())
	{
		cout << it1->first << ":" << it1->second << " ";
		it1++;
	}
	cout << endl;
    //迭代器删除
	mymap.erase(mymap.begin());
	auto it2 = mymap.begin();
	while (it2 != mymap.end())
	{
		cout << it2->first << ":" << it2->second << " ";
		it2++;
	}
	cout << endl;
    //删除指定的key所对应的pair
	mymap.erase(4);
	auto it3 = mymap.begin();
	while (it3 != mymap.end())
	{
		cout << it3->first << ":" << it3->second << " ";
		it3++;
	}
	cout << endl;
 
	return 0;
}

 4.3 查找

//查找k,返回k所在的迭代器,没有找到返回end() 
iterator find(const key_type& k);

//查找k,返回k的个数 
size_type count(const key_type& k) const;
int main()
{
	//这里使用int()默认初始化为0
	map<string, int> mymap;
	mymap.insert({ "苹果",int() });
	mymap.insert({ "香蕉",int() });
	mymap.insert({ "西瓜",int() });
	mymap.insert({ "菠萝",int() });
	mymap.insert({ "苹果",int() });
	mymap.insert({ "柑橘",int() });
	mymap.insert({ "苹果",int() });
	auto it1 = mymap.begin();
	while (it1 != mymap.end())
	{
		cout << it1->first << ":" << it1->second << " ";
		it1++;
	}
	cout << endl;
 
	auto it = mymap.find("苹果");
	cout << it->first << ":" << it->second << endl;
 
	int count = mymap.count("苹果");
	if (count)
	{
		cout << "苹果存在" << endl;
	}
	else
	{
		cout << "苹果不存在" << endl;
	}
 
	return 0;
}
 

 


5. map的数据修改

map⽀持修改mapped_type 数据,不⽀持修改key数据,修改关键字数据,破坏了底层搜
索树的结构

map第⼀个⽀持修改的⽅式时通过迭代器,迭代器遍历时或者find返回key所在的iterator修改,map还有⼀个⾮常重要的修改接⼝operator[],但是operator[]不仅仅⽀持修改,还⽀持插⼊数据和查找数据,所以他是⼀个多功能复合接⼝ 

需要注意从内部实现⻆度,map这⾥把我们传统说的value值,给的是T类型,typedef为
mapped_type。⽽value_type是红⿊树结点中存储的pair键值对值。⽇常使⽤我们还是习惯将这⾥的T映射值叫做value 

Member types
key_type        -> The first template parameter (Key)

mapped_type     -> The second template parameter (T)

value_type      -> pair<const key_type,mapped_type>

查找k,返回k所在的迭代器,没有找到返回end(),如果找到了通过iterator可以修改key对应的mapped_type值

iterator find (const key_type& k);


6. map的operator[]

map的operator[]的功能非常齐全,包含着:插入,查找和修改

operator[]的底层是使用insert实现的

#include<iostream>
#include<map>
#include<string>
using namespace std;
int main()
{
	// 利⽤[]插⼊+修改功能,巧妙实现统计⽔果出现的次数
	string arr[] = { "苹果", "西⽠", "苹果", "西⽠", "苹果", "苹果", "西⽠",
	"苹果", "⾹蕉", "苹果", "⾹蕉" };
	map<string, int> countMap;
	for (const auto& str : arr)
	{
		// []先查找⽔果在不在map中
		// 1、不在,说明⽔果第⼀次出现,则插⼊{⽔果, 0},同时返回次数的引⽤,
		//++⼀下就变成1次了
			// 2、在,则返回⽔果对应的次数++
			countMap[str]++;
	}
	for (const auto& e : countMap)
	{
		cout << e.first << ":" << e.second << endl;
	}
	cout << endl;
	return 0;
}

1、如果k不在map中,insert会插⼊k和mapped_type默认值,同时[]返回结点中存储
mapped_type值的引⽤,那么我们可以通过引⽤修改返映射值。所以[]具备了插⼊+修改功能

//operator[]
int main()
{
	map<int, string> mymap;
	mymap.insert({ 1,"first" });
 
	//1.原来的key不存在->插入+修改
	//key不存在->插入{2,""};
	mymap[2];
 
	//key不存在->插入+修改{3,"third"};
	mymap[3] = "third";
 
	return 0;
}

  2、如果k在map中,insert会插⼊失败,但是insert返回pair对象的first是指向key结点的
迭代器,返回值同时[]返回结点中存储mapped_type值的引⽤,所以[]具备了查找+修改的功能

//operator[]
int main()
{
	map<int, string> mymap;
	mymap.insert({ 1,"first" });
 
	//2.原来的key存在->查找+修改
	//key存在->查找,但是必须确定要查找的元素一定存在
	cout << mymap[2] << endl;
 
	//key存在->修改
	mymap[3] = "third_change";
	cout << mymap[3] << endl;
 
	return 0;
}


7. multimap和map的差异

multimap和map的使⽤基本完全类似,主要区别点在于multimap⽀持关键值key冗余,那么
insert/find/count/erase都围绕着⽀持关键值key冗余有所差异,这⾥跟set和multiset完全⼀样,⽐如find时,有多个key,返回中序第⼀个

   

其次就是multimap不⽀持[],因为⽀持key冗余,[]就只能⽀持插⼊了,不能⽀持修改


 完结撒花~

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

04 springboot-工程搭建案例(多环境部署,数据源, Swagger, 国际化,工具类)

项目搭建模板(多环境切换) springboot系列&#xff0c;最近持续更新中&#xff0c;如需要请关注 如果你觉得我分享的内容或者我的努力对你有帮助&#xff0c;或者你只是想表达对我的支持和鼓励&#xff0c;请考虑给我点赞、评论、收藏。您的鼓励是我前进的动力&#xff0c;让我…

基于CRNN模型的多位数字序列识别的应用【代码+数据集+python环境+GUI系统】

基于CRNN模型的多位数字序列识别的应用【代码数据集python环境GUI系统】 基于CRNN模型的多位数字序列识别的应用【代码数据集python环境GUI系统】 背景意义 多位手写数字识别&#xff0c;即计算机从纸张文档、照片、触摸屏等来源接收并解释可理解的手写数字输入的能力。 随着…

2024软件测试面试秘籍(含答案+文档)

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 Part1 1、你的测试职业发展是什么&#xff1f; 测试经验越多&#xff0c;测试能力越高。所以我的职业发展是需要时间积累的&#xff0c;一步步向着高级测试工程师…

低代码可视化-uniapp海报可视化设计-代码生成

在uni-app中&#xff0c;海报生成器通常是通过集成特定的插件或组件来实现的&#xff0c;这些插件或组件提供了生成海报所需的功能和灵活性。我们采用了lime-painter海报组件。lime-painter是一款canvas海报组件&#xff0c;可以更轻松地生成海报。它支持通过JSON及Template的方…

【Linux】如何升级宝塔面板

执行命令&#xff0c;即可升级 curl https://io.bt.sy/install/update_panel.sh|bash

【Unity 实用工具篇】 | UGUI 循环列表 SuperScrollView,快速上手使用

前言 【Unity 实用工具篇】 | UGUI 循环列表 SuperScrollView&#xff0c;快速上手使用一、UGUI ScrollRect拓展插件&#xff1a;SuperScrollView1.1 介绍1.2 效果展示1.3 使用说明及下载 二、SuperScrollView 快速上手使用2.1 LoopListView22.2 LoopGridView2.3 LoopStaggered…

【Python爬虫】获取汽车之家车型配置附代码(2024.10)

参考大哥&#xff0c;感谢大哥&#xff1a;https://blog.csdn.net/weixin_43498642/article/details/136896338 【任务目标】 工作需要想更方便地下载汽车之家某车系配置清单&#xff1b;&#xff08;垃圾汽车之家不给下载导出表格&#xff0c;配置页叉掉了车系要出来还要重新…

提问: 监督学习, 无监督学习, 机器学习, 深度学习的关系? (通义千问2.5的回答)

前言: 以下内容由AI大模型通义千问大模型2.5生成 监督学习, 无监督学习, 机器学习, 深度学习的关系? 监督学习、无监督学习、机器学习和深度学习是人工智能领域的几个重要概念&#xff0c;它们之间存在一定的关系和区别。下面我将详细解释这些概念及其相互之间的关系&#xf…

Unity中使用UnityEvent遇到Bug

UnityEvent绑定过程中&#xff0c;放在Start&#xff08;&#xff09;中绑定会报错&#xff08;通过脚本添加UnityEvent事件脚本&#xff0c;绑定&#xff09; 绑定事件放在OnEnable&#xff08;&#xff09;中不会报错&#xff0c;但是依然不可以立刻添加UnityEvent事件脚本紧…

GeoWebCache1.26调用ArcGIS切片

GeoServer GeoWebCache (osgeo.org) 一、版本需要适配&#xff1a;Geoserver与GeoWebCache、jdk等的版本适配对照 ​ 查看来源 二、准备工作 1、数据&#xff1a;Arcgis标准的切片&#xff0c;通过ArcGIS Server发布的切片文件&#xff0c;注意切片的存储格式为exploded&…

rust入门基础总结

文章目录 前言1、输出格式规范一、占位符相关&#xff08;一&#xff09;{}与{:?} 二、参数替换方式&#xff08;一&#xff09;位置参数&#xff08;二&#xff09;具名参数 三、格式化参数&#xff08;一&#xff09;宽度&#xff08;二&#xff09;对齐&#xff08;三&…

电脑异常情况总结

文章目录 笔记本无症状息屏黑屏 笔记本无症状息屏黑屏 &#x1f34e; 问题描述&#xff1a; 息屏导致黑屏&#xff1b;依次操作计算机--》右键--》管理--》事件查看器--》Windows日志--》系统&#xff1b;从息屏到异常黑屏之间出现了很多错误&#xff0c;如下&#xff1a;事件…

如何区别医疗器械唯一标识(UDI)、医用耗材统一标识码(HCBS)和医保医用耗材编码

医疗器械唯一标识&#xff08;UDI&#xff09;、医用耗材统一标识码&#xff08;HCBS&#xff09;和医保医用耗材编码三种重要标识&#xff0c;在医疗领域发挥着举足轻重的作用。 医疗器械唯一标识UDI码是被比喻成医疗器械产品的“身份证”&#xff08;每个人都有&#xff09;…

「AIGC」n8n AI Agent开源的工作流自动化工具

n8n AI Agent 是一个利用大型语言模型(LLMs)来设计和构建智能体(agents)的工具,这些智能体能够执行一系列复杂的任务,如理解指令、模仿类人推理,以及从用户命令中理解隐含意图。n8n AI Agent 的核心在于构建一系列提示(prompts),使 LLM 能够模拟自主行为。 传送门→ …

鸿蒙软件开发中常见的如何快速自动生成二维码?QRCode组件

QRCode 用于显示单个二维码的组件。 说明&#xff1a; 该组件从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 二维码组件的像素点数量与内容有关&#xff0c;当组件尺寸过小时&#xff0c;可能出现无法展示内容的情况&…

电脑输入账号密码后,屏幕黑屏只有鼠标解决办法

最近办公电脑出现了两次输入密码后,屏幕黑屏之后鼠标能动的问题,只能有手机查一些资料尝试自己解决,具体什么原因导致的暂时还不清楚。解决这个问题大概有两个方案吧&#xff0c;第一次黑屏用的第一个方案&#xff0c;第二次发现第一个方案不好用了就用的第二个方案。 方案一 …

【Python-AI篇】人工智能机器学习

1. 机器学习简介 1.1 机器学习流程 获取数据 SKLEARN数据集查看数据分布数据集分类 数据基本处理 缺省值处理缩小数据范围异常数据处理数据分割类别不平衡数据处理方式 特征工程机器学习(算法) K-近邻算法线性回归线性回归的改进-岭回归逻辑回归(分类)决策树朴素贝叶斯SVMEM算…

创建型模式-----(单例模式)

目录 基本概念 饿汉式&#xff1a; 懒汉式&#xff1a; 上锁双判空版本 std::call_once版本&#xff1a; C11标准后局部静态变量版本&#xff1a; 项目中单例模板的应用 基本概念 单例模式&#xff1a;在程序运行期间只有一份&#xff0c;与程序生存周期一样&#xff0c;…

记一行代码顺序引起的事故

01 前情回顾 在这里跟同学们分享一个前几天在线上遇见的 bug… bug描述&#xff1a;客户端轮询服务端接口获取数据做打字机效果展示&#xff0c;会偶现输出到一半就停止不动了&#xff0c;但是数据还没输出完&#xff08;如下图&#xff0c;到红色部分就卡住了&#xff09;。…

【Axure高保真原型】移动案例

今天和大家分享多个常用的移动案例的原型模板&#xff0c;包括轮盘滑动控制元件移动、页面按钮控制元件移动、鼠标单击控制元件移动、元件跟随鼠标移动、鼠标拖动控制元件移动、键盘方向键控制元件移动&#xff0c;具体效果可以点击下方视频观看或打开下方预览地址查看哦 【原…