面向对象程序设计——mapの简析

1.map的定义

Key就是map底层关键字的类型,T是map底层value的类型,set默认要求Key⽀持⼩于⽐较,如果不⽀持或者需要的话可以⾃⾏实现仿函数传给第⼆个模版参数,map底层存储数据的 内存是从空间配置器申请的。⼀般情况下,我们都不需要传后两个模版参数。map底层是⽤红⿊树实现,增删查改效率是O(logN) ,迭代器遍历是⾛的中序,所以是按key有序顺序遍历的

1.1map的构造

显式实例化直接构造 

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

匿名对象构造 

//map
int main()
{//显式定义map<string, string> dict;pair<string, string> key("first", "第一个");dict.insert(key);//匿名对象dict.insert(pair<string, string>("second", "第二个"));return 0;
}

 函数模版构造

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

 小tips:

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

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

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

2.pair

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

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

3.map的增删查 

 3.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,注意这里的pair与map底层的pair不同,若插入成功就会返回pair<插入后的key的迭代器,true>,插入失败就返回pair<原来就存在相同key的迭代器,false>,这对后面的operator[]有很大作用

//单个数据插⼊,如果已经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;
}

 3.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所对应的pairmymap.erase(4);auto it3 = mymap.begin();while (it3 != mymap.end()){cout << it3->first << ":" << it3->second << " ";it3++;}cout << endl;return 0;
}

 3.3查找 

//查找k,返回k所在的迭代器,没有找到返回end() 
iterator find(const key_type& k);
//查找k,返回k的个数 
size_type count(const key_type& k) const;
int main()
{//这里使用int()默认初始化为0map<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;
}

4.operatpr[]间接实现增删查改

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

5.multimap和map的差异

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

6.实战代码练习

 138.随机链表的复制

思路解析:

本题的难点就是如何深拷贝一个随机链表,随机链表的定义就是每一个节点都有两个指针,一个指针next指向下一个节点,另一个随机指针指向任意节点,难点就是拷贝这两个指针

不过在学习了map后我们可以使用映射拷贝,即首先创建一个新的链表首先拷贝原链表以及next指针,然后将该链表存储在一个map中,使用每个节点本身当做key,random指针当做value,之后处理拷贝而来的新链表中的random指针,使用map中的key做映射,保证random在拷贝后链表中的相对位置与原链表的相同,最后返回拷贝而来的新链表的头结点

/*
// Definition for a Node.
class Node {
public:int val;Node* next;Node* random;Node(int _val) {val = _val;next = NULL;random = NULL;}
};
*/class Solution {
public:Node* copyRandomList(Node* head) {map<Node*,Node*> mapNode;Node* copyhead = nullptr;Node* copytail = nullptr;Node* cur = head;//拷贝原链表映射到map中并且创建一个新链表拷贝原链表while(cur){//初始时刻if(copytail == nullptr){copyhead = copytail = new Node(cur->val);}else{//从尾节点开始接入新节点copytail->next = new Node(cur->val);copytail = copytail->next;}//映射拷贝到map中mapNode[cur] = copytail;cur = cur->next;}//处理random指针,copy与cur指针同时运动cur = head;Node* copy = copyhead;while(cur){if(cur->random == nullptr){copy->random = nullptr;}else{//使用映射处理random节点copy->random = mapNode[cur->random];}cur = cur->next;copy = copy->next;}return copyhead;}
};

 

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

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

相关文章

OpenBayes 教程上新|让虚拟偶像活起来!LivePortrait 实现超逼真表情迁移

过去&#xff0c;使用单一图像生成动态视频效果需要复杂的动画技术和大量的手工操作。特别是在控制眼睛和嘴唇等细节上&#xff0c;耗时且难以实现逼真的同步效果。 LivePortrait 在最新版本中通过精确的画像编辑和视频编辑等功能&#xff0c;极大地简化了这一过程。创作者可以…

调度_命令行_环境变量

linux的进程调度算法 饥饿问题 新建进程/时间片结束进程&#xff0c;若放回active&#xff0c;很可能该进程优先级太高&#xff0c;下一个还是执行该进程&#xff0c;导致不断执行同一进程&#xff0c;各进程调度不均衡。 饥饿问题解决 新建进程不能到active&#xff0c;要到…

论文大杀器!分享4款ai论文写作工具软件

在当今学术研究和论文写作领域&#xff0c;AI技术的应用已经变得越来越普遍。这些工具不仅能够提高写作效率&#xff0c;还能帮助研究人员生成高质量的论文内容。本文将重点介绍四款优秀的AI论文写作工具&#xff0c;并特别推荐千笔-AIPassPaper。 一、千笔-AIPassPaper 传送门…

RTR_Chapter_6 上

第六章 纹理 表面纹理&#xff08;texture&#xff09;是指其外观和给人的视觉感受&#xff0c;就像是一幅油画的图案一样。而在计算机图形学中&#xff0c;纹理化则指的是一个过程&#xff0c;即通过使用一些图像、函数或者其他数据&#xff0c;来对每个表面位置的外观表现进行…

看Threejs好玩示例,学习创新与技术(React-three-fiber)

什么&#xff0c;竟有人把ThreeJS和React绑定在一起&#xff0c;混着用&#xff1f; 1、VUE劫持问题 暂先把今天的问题先放一边&#xff0c;先简单回顾下vue劫持的情况。vue会把data里面的数据自动转换为属性&#xff0c;方便界面与数据交互。这本身是没有任何问题&#xff0…

内网穿透(当使用支付宝沙箱的时候需要内网穿透进行回调)

内网穿透 一、为什么要使用内网穿透&#xff1a; 内网穿透也称内网映射&#xff0c;简单来说就是让外网可以访问你的内网&#xff1a;把自己的内网(主机)当做服务器&#xff0c;让外网访问 二、安装路由侠 路由侠-局域网变公网 (luyouxia.com) 安装成功如下&#xff1a; 三…

全栈开发(一):springBoot3+mysql初始化

1.开发环境准备 1.开发工具 2.jdk下载 官网下载java17 3.java环境变量配置 用户变量&#xff1a; ①.JAVA_HOME ②.path 4.mysql下载 b站随便搜 5.新建项目 6.maven配置 可以下载zip放到目录里 这里是配置好的 repository文件夹&#xff1a;为maven提供下载的文件存放…

Face++API调用

人脸检测API调用 import requests import json #将自己的KEY和Secret进行替换 API_KEYyour_API_KET API_SECRETyour_API_Secret# 人脸识别的URL URL https://api-cn.faceplusplus.com/facepp/v3/detect# 请求参数,需要什么参数传入什么参数 data {"api_key":API…

【LVIO-SLAM】SVD分解,最小二乘与EKF

【LVIO-SLAM】SVD分解与应用推导 1.1 线性最小而二乘1.2 SVD分解算法流程问题描述算法流程算法复杂度总结 1.3 非线性最小二乘1.4 EKF融合 KF/ EKF推导过程 1.1 线性最小而二乘 针对A是任意矩阵的话使用SVD分解求解&#xff0c;其中U是AA转置的特征值&#xff0c;V是AA转置A的特…

Python3 爬虫教程 - Web 网页基础

Web网页基础 1&#xff0c;网页的组成HTMLcssJavaScript2&#xff0c;网页的结构 3&#xff0c;节点树及节点间的关系4&#xff0c;选择器开头代表选择 id&#xff0c;其后紧跟 id 的名称。如&#xff1a;div 节点的 id 为 container&#xff0c;那么就可以表示为 #container 1…

828华为云征文 | 云服务器Flexus X实例,Docker集成搭建Jenkins CI/CD平台

828华为云征文 | 云服务器Flexus X实例&#xff0c;Docker集成搭建Jenkins CI/CD平台 Jenkins 是一个开源的自动化服务器&#xff0c;用于持续集成&#xff08;CI&#xff09;和持续交付&#xff08;CD&#xff09;软件项目。它允许开发人员在软件开发过程中自动化各种任务&…

进阶SpringBoot之集合 Redis

&#xff08;在跑 Redis 测试之前&#xff0c;需要先安装 Redis&#xff0c;并开启 Redis 服务&#xff09; Spring Boot 项目添加依赖 NoSQL -> Spring Data Redis pom.xml 文件如下 <dependencies><dependency><groupId>org.springframework.boot<…

【深度】为GPT-5而生的「草莓」模型!从快思考—慢思考到Self-play RL的强化学习框架

原创 超 超的闲思世界 2024年09月11日 19:17 北京 9月11日消息&#xff0c;据外媒The Information昨晚报道&#xff0c;OpenAI的新模型「草莓」&#xff08;Strawberry&#xff09;&#xff0c;将在未来两周内作为ChatGPT服务的一部分发布。 「草莓」项目是OpenAI盛传已久的…

得物App荣获新奖项,科技创新助力高质量发展

近日&#xff0c;备受瞩目的2024中国国际服务贸易交易会&#xff08;简称“服贸会”&#xff09;在北京盛大开幕&#xff0c;这一全球唯一的国家级、国际性、综合型服务贸易盛会再次汇聚了全球服务贸易领域的精英与前沿成果。服贸会由商务部和北京市政府携手打造&#xff0c;并…

常见框架漏洞复现

1、Thinkphp5x远程命令执行及getshell 1、环境配置 靶场:vulhub/thinkphp/5-rce docker-compose up -d 2、漏洞利用 漏洞根本源于 thinkphp/library/think/Request.php 中method方法可以进行变量覆盖&#xff0c;通过覆盖类的核心属性filter导致rce&#xff0c;其攻击点较为…

VMamba: Visual State Space Model 论文总结 + 源码解析

题目&#xff1a;VMamba: Visual State Space Model&#xff08;视觉状态空间模型&#xff09; 论文&#xff1a;[2401.10166] VMamba: Visual State Space Model (arxiv.org) 源码&#xff1a;https://arxiv.org/pdf/2401.10166 (github.com) 目录 一、摘要 二、引言 三、方…

全栈开发(四):使用springBoot3+mybatis-plus+mysql开发restful的增删改查接口

1.创建user文件夹 作为增删改查的根包 路径 src/main/java/com.example.demo/user 2.文件夹里文件作用介绍 1.User(实体类) package com.example.demo.user; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.IdType; impo…

计算机毕业设计之:基于微信小程序的疫苗预约系统的设计与实现(源码+文档+讲解)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

2024全球超模大赛(北京|山东|内蒙三城联动)顺利举办

近日&#xff0c;2024 全球超模大赛&#xff08;北京|山东|内蒙&#xff09;三城联动暨新国潮文化赛事主题发布会在紫薇美力集团国贸鲁采赋盛大举行。此次发布会旨在鼓励优质模特共同传播中国传统文化&#xff0c;让其在全球范围内绽放光彩&#xff0c;展现中国人的骄傲与风采&…

【我的 PWN 学习手札】House of Botcake —— tcache key 绕过

参考自看雪课程&#xff1a;PWN探索篇 前言 我们知道&#xff0c;自对 tcachebin 添加了 key 进行了 double free 检查后&#xff0c;利用起来薛微有些困难。double free 绕过检查机制&#xff0c;实则是因为释放时会检查 tcachebin 对应 size 的所有 free chunk。那么如果第二…