C++ —— map系列的使用

news/2024/10/23 15:04:21/

目录

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所对应的pairmymap.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()默认初始化为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;
}

 


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冗余,[]就只能⽀持插⼊了,不能⽀持修改


 完结撒花~


http://www.ppmy.cn/news/1541361.html

相关文章

Spring的底层原理

文章目录 1. Bean的生命周期2. 推断构造方法3. 依赖注入4. 初始化前5. 初始化6. 初始化后7. AOP8. Spring事务9. Spring事务失效10. Configuration11. 循环依赖12. Lazy 1. Bean的生命周期 UserService.class --> 推断构造方法 --> 普通对象 --> 依赖注入 --> 初始…

nosql课本习题

nosql题目 1. 文档数据库相比其他 NoSQL 的突出优势和特点是什么&#xff1f; 答案&#xff1a; 文档数据库的突出优势在于它的灵活性和可扩展性。不同于传统的关系型数据库&#xff0c;文档数据库允许存储半结构化和非结构化数据&#xff0c;每个文档可以有不同的字段&#x…

简述微服务高可用之Sentinel、Seate

简述微服务高可用之Sentinel、Seate使用 下文主要讲述使用sentinel,如何降级限流熔断及如何使用seata管理分布式事务 sentinel服务端安装与使用 1、下载 进入https://github.com/alibaba/Sentinel/releases 根据你的需求进行下载对应版本 我这里是JDK17 下载的1.8.8版本&am…

网络安全——防火墙技术

目录 前言基本概念常见防火墙技术防火墙的主要功能防火墙的不足之处相关题目1.组织外部未授权用户访问内部网络2.DMZ区3.包过滤防火墙和代理服务防火墙 前言 这是在软件设计师备考时编写的资料文章&#xff0c;相关内容偏向软件设计师 基本概念 防火墙技术是网络安全领域中的…

Java | Leetcode Java题解之第491题非递减子序列

题目&#xff1a; 题解&#xff1a; class Solution {List<Integer> temp new ArrayList<Integer>();List<List<Integer>> ans new ArrayList<List<Integer>>();public List<List<Integer>> findSubsequences(int[] nums) …

走廊泼水节——求维持最小生成树的完全图的最小边权和

题目 思考 代码 #include <bits/stdc.h> using namespace std; const int N 6010; const int M N; int p[N], sz[N]; struct edge{int a;int b;int c;bool operator < (const edge& v) const{return c < v.c;} }e[M]; int find(int x) {if(p[x] ! x) p[x] …

vscode 配置构建、调试QT项目

1. 背景是已经安装好了QT和QT相关的所有依赖包 https://mp.csdn.net/mp_blog/creation/editor/142974086 2. 配置环境变量 找不到或者忘记在哪里可以使用指令查询 3.插件安装Qt Support、 Qt tools、Qt UI等 Cmake、Cmake Tools 等 C/C等 settings.json 配置 此部分是根据一些报…

c语言基础程序——经典100道实例。

c语言基础程序——经典100道实例 001&#xff0c; 组无重复数字的数002&#xff0c;企业发放的奖金根据利润提成003&#xff0c;完全平方数004&#xff0c;判断当天是这一年的第几天005&#xff0c;三个数由小到大输出006&#xff0c;输出字母C图案007&#xff0c;特殊图案008&…