【C++】map详解

【C++】map详解
📢博客主页:https://blog.ZEEKLOG.net/2301_779549673
📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
📢本文由 JohnKi 原创,首发于 ZEEKLOG🙉
📢未来很长,值得我们全力奔赴更美好的生活✨

在这里插入图片描述

文章目录


📢前言

map的结构和set很类似,部分功能就不演示了,上一篇博客中有

在这里插入图片描述


Map 是 C++ 中非常重要的关联容器之一。它以键值对的形式存储数据,其中每个键都是唯一的,这意味着不能有重复的键。如果尝试插入一个已存在的键,将会覆盖该键对应的值。

Map 的内部结构是红黑树,这使得它具有很多优点。首先,数据是有序的,这有助于高效地进行查找、插入和删除操作。查找、插入、删除的平均和最坏时间复杂度都是 O (log n),其中 n 是 map 中元素的个数。

例如,当我们需要存储学生的学号和姓名时,可以使用 map<int, string>,其中学号作为键,姓名作为值。这样可以通过学号快速地找到对应的学生姓名。

Map 的键和值可以是任意类型,但需要注意的是,如果键是自定义类型,需要为该类型提供小于运算符的重载,以便 map 能够对键进行排序。

在实际应用中,Map 非常适合用于需要快速查找和存储键值对的场景。比如,在字典应用中,可以将单词作为键,释义作为值,方便用户快速查询单词的含义。

总之,Map 以其高效的查找、插入和删除操作,以及有序性和唯一键的特点,在 C++ 编程中有着广泛的应用。


🏳️‍🌈一、pair类型介绍

在 C++ 中,pair类是一种模板类型,定义在<utility>头文件中。它将两个不同类型的值组合成一个单一的对象。对于map容器来说,map中的每个元素都是一个pair类型。map底层的红黑树节点中的数据,使用pair<Key,T>存储键值对数据。

typedef pair<const Key, T> value_type;template<classT1,classT2>structpair{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<classU,classV>pair(const pair<U, V>& pr):first(pr.first),second(pr.second){}};// 内联函数,建议编译器在调用该函数的地方直接插入函数体的代码template<classT1,classT2>inline pair<T1, T2>make_pair(T1 x, T2 y){return( pair<T1, T2>(x, y));}

🏳️‍🌈二、map的增删查

map的增删查关注以下几个接口即可:

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

Member types key_type -> The first templateparameter(Key) mapped_type -> The second templateparameter(T) value_type -> pair<const key_type, mapped_type>// 单个数据插⼊,如果已经key存在则插⼊失败,key存在相等value不相等也会插⼊失败 pair<iterator,bool>insert(const value_type& val);// 列表插⼊,已经在容器中存在的值不会插⼊voidinsert(initializer_list<value_type> il);// 迭代器区间插⼊,已经在容器中存在的值不会插⼊template<classInputIterator>voidinsert(InputIterator first, InputIterator last);// 查找k,返回k所在的迭代器,没有找到返回end() iterator find(const key_type& k);// 查找k,返回k的个数 size_type count(const key_type& k)const;// 删除⼀个迭代器位置的值 iterator erase(const_iterator position);// 删除k,k存在返回0,存在返回1 size_type erase(const key_type& k);// 删除⼀段迭代器区间的值 iterator erase(const_iterator first, const_iterator last);// 返回⼤于等k位置的迭代器 iterator lower_bound(const key_type& k);// 返回⼤于k位置的迭代器 const_iterator lower_bound(const key_type& k)const

🏳️‍🌈三、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 templateparameter(Key) mapped_type -> The second templateparameter(T) value_type -> pair<const key_type,mapped_type>// 查找k,返回k所在的迭代器,没有找到返回end(),如果找到了通过iterator可以修改key对应的 mapped_type值 iterator find(const key_type& k);// ⽂档中对insert返回值的说明// The single element versions (1) return a pair, with its member pair::first//set to an iterator pointing to either the newly inserted element or to the//element with an equivalent key in the map. The pair::second element in the pair//is set to true if a new element was inserted or false if an equivalent key//already existed.// 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<iterator,bool>insert(const value_type& val); mapped_type&operator[](const key_type& k);// operator的内部实现 mapped_type&operator[](const key_type& k){// 1、如果k不在map中,insert会插⼊k和mapped_type默认值,同时[]返回结点中存储//mapped_type值的引⽤,那么我们可以通过引⽤修改返映射值。所以[]具备了插⼊+修改功能// 2、如果k在map中,insert会插⼊失败,但是insert返回pair对象的first是指向key结点的//迭代器,返回值同时[]返回结点中存储mapped_type值的引⽤,所以[]具备了查找+修改的功能 pair<iterator,bool> ret =insert({ k,mapped_type()}); iterator it = ret.first;return it->second;}

🏳️‍🌈四、使用样例

构造遍历及增删查使用样例

#include<iostream>#include<map>usingnamespace std;intmain(){// initializer_list构造及迭代遍历 map<string, string> dict ={{"left","左边"},{"right","右边"},{"insert","插⼊"},{"string","字符串"}};//map<string, string>::iterator it = dict.begin();auto it = dict.begin();while(it != dict.end()){//cout << (*it).first <<":"<<(*it).second << endl;// map的迭代基本都使⽤operator->,这⾥省略了⼀个->// 第⼀个->是迭代器运算符重载,返回pair*,第⼆个箭头是结构指针解引⽤取//pair数据//cout << it.operator->()->first << ":" << it.operator->()-> second << endl; cout << it->first <<":"<< it->second << endl;++it;} cout << endl;// insert插⼊pair对象的4种⽅式,对⽐之下,最后⼀种最⽅便 pair<string, string>kv1("first","第⼀个"); dict.insert(kv1); dict.insert(pair<string, string>("second","第⼆个")); dict.insert(make_pair("sort","排序")); dict.insert({"auto","⾃动的"});// "left"已经存在,插⼊失败 dict.insert({"left","左边,剩余"});// 范围for遍历for(constauto& e : dict){ cout << e.first <<":"<< e.second << endl;} cout << endl; string str;while(cin >> str){auto ret = dict.find(str);if(ret != dict.end()){ cout <<"->"<< ret->second << endl;}else{ cout <<"⽆此单词,请重新输⼊"<< endl;}}// erase等接⼝跟set完全类似,这⾥就不演⽰讲解了return0;}

map的迭代器和[]功能样例:

#include<iostream>#include<map>#include<string>usingnamespace std;intmain(){// 利⽤find和iterator修改功能,统计⽔果出现的次数 string arr[]={"苹果","西⽠","苹果","西⽠","苹果","苹果","西⽠","苹果","⾹蕉","苹果","⾹蕉"}; map<string,int> countMap;for(constauto& str : arr){// 先查找⽔果在不在map中// 1、不在,说明⽔果第⼀次出现,则插⼊{⽔果, 1}// 2、在,则查找到的节点中⽔果对应的次数++auto ret = countMap.find(str);if(ret == countMap.end()){ countMap.insert({ str,1});}else{ ret->second++;}}for(constauto& e : countMap){ cout << e.first <<":"<< e.second << endl;} cout << endl;return0;}#include<iostream>#include<map>#include<string>usingnamespace std;intmain(){// 利⽤[]插⼊+修改功能,巧妙实现统计⽔果出现的次数 string arr[]={"苹果","西⽠","苹果","西⽠","苹果","苹果","西⽠","苹果","⾹蕉","苹果","⾹蕉"}; map<string,int> countMap;for(constauto& str : arr){// []先查找⽔果在不在map中// 1、不在,说明⽔果第⼀次出现,则插⼊{⽔果, 0},同时返回次数的引⽤,++⼀下就变成1次了// 2、在,则返回⽔果对应的次数++ countMap[str]++;}for(constauto& e : countMap){ cout << e.first <<":"<< e.second << endl;} cout << endl;return0;}#include<iostream>#include<map>#include<string>usingnamespace std;intmain(){ map<string, string> dict; dict.insert(make_pair("sort","排序"));// key不存在->插⼊ {"insert", string()} dict["insert"];// 插⼊+修改 dict["left"]="左边";// 修改 dict["left"]="左边、剩余";// key存在->查找 cout << dict["left"]<< endl;return0;}

🏳️‍🌈五、multimap和map的差异

multimap和map的使用基本完全类似,主要区别点在于multimap支持关键值key冗余,那么insert/find/count/erase都围绕着支持关键值key冗余有所差异,这里跟set和multiset完全一样,比如find时,有多个key,返回中序第一个。其次就是multimap不支持门,因为支持key冗余,"就只能支持插入了,不能支持修改。


👥总结


本篇博文对 map 做了一个较为详细的介绍,不知道对你有没有帮助呢

觉得博主写得还不错的三连支持下吧!会继续努力的~

请添加图片描述

Read more

内存暴涨700%背后的惊天真相:AI正在吞噬一切!能源·隐私·绿色三大维度深度拆解

内存暴涨700%背后的惊天真相:AI正在吞噬一切!能源·隐私·绿色三大维度深度拆解

🔥作者简介: 一个平凡而乐于分享的小比特,中南民族大学通信工程专业研究生,研究方向无线联邦学习 🎬擅长领域:驱动开发,嵌入式软件开发,BSP开发 ❄️作者主页:一个平凡而乐于分享的小比特的个人主页 ✨收录专栏:未来思考,本专栏结合当前国家战略和实时政治,对未来行业发展的思考 欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖 🔥内存暴涨700%背后的惊天真相:AI正在吞噬一切!能源·隐私·绿色三大维度深度拆解 |前言| 最近装机的小伙伴们欲哭无泪:DDR5内存价格一路狂飙,部分DRAM现货价格在过去一年暴涨近700% 。大家习惯性吐槽“厂商放火”、“产能不足”,但很少有人看到,这场涨价风暴的真正推手,是那只名为“AI”的巨兽。 当你还在为多花几百块钱买内存心疼时,国家正在西部荒漠建起一座座数据中心,科技巨头正在为“吃电怪兽”抢购每一颗芯片。2026年,大型科技公司的AI相关投资预计将达到6500亿美元,较去年增长约80% 。 今天,我们从能源供应、隐私安全、绿色AI 三个维度,结合东数西算、算电协同、

By Ne0inhk
AI实践(8)Skills技能

AI实践(8)Skills技能

AI实践(10)Skills技能 Author: Once Day Date: 2026年3月18日 一位热衷于Linux学习和开发的菜鸟,试图谱写一场冒险之旅,也许终点只是一场白日梦… 漫漫长路,有人对你微笑过嘛… 全系列文章可参考专栏: AI实践成长_Once-Day的博客-ZEEKLOG博客 参考文章:Prompt Engineering Guide提示词技巧 – Claude 中文 - Claude AI 开发技术社区Documentation - Claude API DocsOpenAI for developersSkills(技能) – Claude 中文 - Claude AI 开发技术社区模式库:把工程经验沉淀为 Skills – Claude 中文 - Claude AI 开发技术社区持续学习:把会话复盘沉淀成 Skills – Claude

By Ne0inhk
医疗AI场景下算法编程的深度解析(2026新生培训讲稿)(八)

医疗AI场景下算法编程的深度解析(2026新生培训讲稿)(八)

第15章 模型融合与集成策略 在机器学习竞赛和实际应用中,模型融合(Model Ensemble)是提升预测性能的利器。通过组合多个不同的基模型,集成策略能够综合各个模型的优势,抵消单个模型的偏差和方差,从而获得比任何单一模型更稳定、更准确的预测结果。在医疗AI领域,模型融合同样具有重要价值——面对复杂多模态的医疗数据,单一模型往往难以全面捕捉所有信息,而融合多个异质模型可以提升诊断的鲁棒性和准确性。本章将从集成学习的基本思想出发,系统介绍常见的模型融合方法,包括投票法、平均法、Stacking、Blending等,并通过实战案例展示如何构建融合模型来提升疾病预测性能。 15.1 集成学习的基本思想 集成学习(Ensemble Learning)的核心思想是“三个臭皮匠,顶个诸葛亮”——通过结合多个学习器来完成学习任务,通常可以获得比单一学习器更优越的泛化性能。根据个体学习器的生成方式,集成学习主要分为两大类: * Bagging:并行训练多个独立的基学习器,然后通过平均或投票进行结合。典型代表是随机森林。Bagging主要降低方差。 * Boosting:串行训练基学习

By Ne0inhk
人工智能:自然语言处理在教育领域的应用与实战

人工智能:自然语言处理在教育领域的应用与实战

人工智能:自然语言处理在教育领域的应用与实战 学习目标 💡 理解自然语言处理(NLP)在教育领域的应用场景和重要性 💡 掌握教育领域NLP应用的核心技术(如智能问答、作业批改、个性化学习) 💡 学会使用前沿模型(如BERT、GPT-3)进行教育文本分析 💡 理解教育领域的特殊挑战(如多学科知识、学生认知差异、数据隐私) 💡 通过实战项目,开发一个智能问答系统应用 重点内容 * 教育领域NLP应用的主要场景 * 核心技术(智能问答、作业批改、个性化学习) * 前沿模型(BERT、GPT-3)在教育领域的使用 * 教育领域的特殊挑战 * 实战项目:智能问答系统应用开发 一、教育领域NLP应用的主要场景 1.1 智能问答 1.1.1 智能问答的基本概念 智能问答是通过自然语言与用户进行交互,回答用户问题的程序。在教育领域,智能问答的主要应用场景包括: * 课程问答:回答课程相关的问题(如“什么是机器学习”

By Ne0inhk