【C++】map详解

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

在这里插入图片描述

在这里插入图片描述

文章目录

  • 📢前言
  • 🏳️‍🌈一、pair类型介绍
  • 🏳️‍🌈二、map的增删查
  • 🏳️‍🌈三、map的数据修改
  • 🏳️‍🌈四、使用样例
  • 🏳️‍🌈五、multimap和map的差异
  • 👥总结


📢前言

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 <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) );
}

🏳️‍🌈二、map的增删查

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

map增接口,插入的pair键值对数据,跟set所有不同,但是查和删的接口只用关键字key跟set是完全类似的,不过find返回iterator,不仅仅可以确认key在不在,还找到key映射的value,同时通过迭代还可以修改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>// 单个数据插⼊,如果已经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);
// 查找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 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);
// ⽂档中对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>
using namespace std;
int main() {
// 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 (const auto& 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完全类似,这⾥就不演⽰讲解了return 0;
}

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

#include<iostream>
#include<map>
#include<string>
using namespace std;
int main() {// 利⽤find和iterator修改功能,统计⽔果出现的次数string arr[] = { "苹果", "西⽠", "苹果", "西⽠", "苹果", "苹果", "西⽠","苹果", "⾹蕉", "苹果", "⾹蕉"};map<string, int> countMap;for (const auto& str : arr) {
// 先查找⽔果在不在map中
// 1、不在,说明⽔果第⼀次出现,则插⼊{⽔果, 1}
// 2、在,则查找到的节点中⽔果对应的次数++auto ret = countMap.find(str);if (ret == countMap.end()) {countMap.insert({ str, 1 });} else {ret->second++;}}for (const auto& e : countMap) {cout << e.first << ":" << e.second << endl;}cout << endl;return 0;
}#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;
}#include<iostream>
#include<map>
#include<string>
using namespace std;
int main() {map<string, string> dict;dict.insert(make_pair("sort", "排序"));
// key不存在->插⼊ {"insert", string()}dict["insert"];
// 插⼊+修改dict["left"] = "左边";
// 修改dict["left"] = "左边、剩余";
// key存在->查找cout << dict["left"] << endl;return 0;
}

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

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


👥总结


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

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

请添加图片描述

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

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

相关文章

ESP8266使用AT指令完成MQTT功能

ESP8266使用AT指令完成MQTT功能 在esp8266设备中烧录安信可的AT固件之后&#xff0c;进行AT指令完成信息发布&#xff0c;并最终实现在Homeassistant中发布传感器并设置传感器状态。 一、基础指令 以下是完整的步骤和对应的AT指令&#xff1a; 1. 配置ESP8266为Station模式 …

10.8学习

1.CAP ★一致性&#xff08;2PC、3PC、Paxos、Raft&#xff09; ●强一致性&#xff1a;数据库一致性&#xff0c;牺牲了性能 ACID&#xff1a;原子性、一致性、隔离性、持久性 ●弱一致性&#xff1a;数据库和缓存&#xff0c;延迟双删、重试 ●单调读一致性&#xff1a;…

[面试] java开发面经-1

前言 目录 1.看到你的简历里说使用Redis缓存高频数据&#xff0c;说一下Redis的操作 2.说一下Redis的缓存击穿、缓存穿透、缓存雪崩 3.你的项目中使用了ThreadLocal&#xff0c;那么当有两个请求同时发出时&#xff0c;会怎么处理&#xff0c;可以同时处理两个请求吗 4.使用…

01_InfluxDb

InFluxDb 概览课程地址Flux语言安装使用场景底层原理-数据结构数据价值热数据冷数据 数据只写不改InFluxDb 1.8 生态InFluxDb查询语言 TelegrafChronograph_画面插件Kapacitor InFluxDb 2.2 生态InFluxDb查询语言 Telegrapf 集群集群方案 概览 时序数据库,对时序场景有特别的优…

java web gis 快速搭建开发环境_服务端搭建

前言: 链接:https://pan.baidu.com/s/15i7FxthazW0J87D5jWh5ng?pwd32nd 提取码:32nd 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 Java 环境 jdk 1.8 &#xff1b; maven ; 中间件: redis 数据库: postgres 1.4 ; postgis 代码管理: git 客户端 开发工…

【每日一题 | 24.10.8】确定字符串是否是另一个的排列

1. 题目2. 解题思路3. 代码实现&#xff08;AC_Code&#xff09; 上期回顾:【每日一题 | 24.10.7】Fizz Buzz 经典问题 个人主页&#xff1a;C_GUIQU 归属专栏&#xff1a;每日一题 1. 题目 确定字符串是否是另一个的排列 2. 解题思路 题目核心要求&#xff1a;理解字符串排列…

使用最小二乘法画噪声数据的近似曲线

文章目录 问题MATLAB代码验证数据1验证数据2 问题 已知有系列含有噪声的数据&#xff08;x , y&#xff09;用最小二乘法计算m和b。(ymxb) MATLAB代码 disp(This promgram perform a leastsquares fit of an); disp(input data set to a straight line.); n_points input(E…

HTB:Tactics[WriteUP]

目录 连接至HTB服务器并启动靶机 1.Which Nmap switch can we use to enumerate machines when our ping ICMP packets are blocked by the Windows firewall? 2.What does the 3-letter acronym SMB stand for? 3.What port does SMB use to operate at? 4.What comma…

python数据分析与可视化工具介绍-numpy库

NumPy&#xff08;Numerical Python的简称&#xff09;&#xff0c;是科学计算基础的一个库&#xff0c;提供了大量关于科学计算的相关功能&#xff0c;例如&#xff0c;线性变换&#xff0c;数据统计&#xff0c;随机数生成等。其提供的最核心的类型为多维数组类型&#xff08…

DAMA数据管理知识体系(第7章 数据安全)

课本内容 7.1 引言 概要 数据安全包括安全策略和过程的规划、建立与执行&#xff0c;为数据和信息资产提供正确的身份验证、授权、访问和审计数据安全来源要求 利益相关方政府法规特定业务关注点合法访问需求合同义务语境关系图 图7-2 语境关系图&#xff1a;数据安全业务驱动因…

微信小程序python+uniapp毕业论文选题系统设计与实现 lj141

目录 项目介绍具体实现截图开发者工具介绍技术路线性能/安全/负载方面开发语言以及框架介绍python-flask核心代码部分展示python-django核心代码部分展示详细视频演示源码获取 项目介绍 考虑到实际生活中在毕业论文选题管理方面的需要以及对该系统认真的分析,将小程序权限按管…

探索循环神经网络RNN:解锁序列数据的奥秘

在这个数据驱动的时代&#xff0c;机器学习模型已经深入到我们生活的方方面面&#xff0c;从智能推荐系统到自然语言处理&#xff0c;无一不彰显其强大的能力。在众多模型中&#xff0c;循环神经网络&#xff08;Recurrent Neural Network, RNN&#xff09;以其独特的结构和对序…

STM32-HAL库 驱动DS18B20温度传感器 -- 2024.10.8

目录 一、教程简介 二、驱动理论讲解 三、CubeMX生成底层代码 四、Keil5编写代码 五、实验结果 一、教程简介 本教程面向初学者&#xff0c;只介绍DS18B20的常用功能&#xff0c;但也能满足大部分的运用需求。跟着本教程操作&#xff0c;可在10分钟内解决DS18b20通信难题。…

基于uniapp+django微信小程序 食品安全信息管理系统

目录 项目介绍具体实现截图开发者工具介绍技术路线性能/安全/负载方面开发语言以及框架介绍python-flask核心代码部分展示python-django核心代码部分展示详细视频演示源码获取 项目介绍 食品安全信息管理系统设计的目的是为用户提供食品信息、科普专栏、食品检测、检测结果、交…

Chromium 中js Fetch API接口c++代码实现(二)

Chromium 中JavaScript Fetch API接口c代码实现&#xff08;一&#xff09;-CSDN博客 接着上一篇继续介绍调用&#xff0c;上函数堆栈。 1、打开http://192.168.8.1/chfs/shared/test/test02.html 此标签进程ID12484&#xff0c; 2、打开vs附加上此进程ID12484 3、点击页面测…

Java--IO高级流

缓冲流 缓冲流,也叫高效流&#xff0c;是对4个基本的FileXxx 流的增强&#xff0c;所以也是4个流&#xff0c;按照数据类型分类&#xff1a; 字节缓冲流&#xff1a;BufferedInputStream&#xff0c;BufferedOutputStream 字符缓冲流&#xff1a;BufferedReader&#xff0c;Buf…

用友Yonbuilder 平台使用教程序

用友Yonbuilder 平台使用教程 目录概述需求&#xff1a; 设计思路实现思路分析 免费下载参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better result,wait for change,c…

环形链表(c语言)

1.//环形链表 //输入&#xff1a;head [3,2,0,-4], pos 1 //输出&#xff1a;true //解释&#xff1a;链表中有一个环&#xff0c;其尾部连接到第二个节点。 //输入&#xff1a;head [1, 2], pos 0 //输出&#xff1a;true //解释&#xff1a;链表中有一个环&#xff0c;其…

【机器学习】线性回归算法简介 及 数学实现方法

线性回归 简介 利用 回归方程(函数) 对 一个或多个自变量(特征值)和因变量(目标值)之间 关系进行建模的一种分析方式。 数学公式&#xff1a; ℎ_(w) w_1x_1 w_2x_2 w_3x_3 … b w^Txb 概念 ​ 利用回归方程(函数) 对 一个或多个自变量(特征值)和因变量(目标值)之间 关…

AI先驱荣获2024诺贝尔物理学奖

瑞典皇家科学院10月8日宣布&#xff0c;将2024年诺贝尔物理学奖授予John J. Hopfield和Geoffrey E. Hinton&#xff0c;以表彰他们利用人工神经网络实现机器学习的奠基性发现和发明。 John J. Hopfield&#xff08;约翰J霍普菲尔德&#xff09;美国新泽西州普林斯顿大学 Geoff…