c++ map

map类的介绍

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

cpp 复制代码
template < class Key, // map::key_type
 class T, // map::mapped_type
 class Compare = less<Key>, // map::key_compare
 class Alloc = allocator<pair<const Key,T> > // 
map::allocator_type
 > class map;

pair类型介绍

map底层的红黑树节点中的数据,使用pair存储键值对数据。

pair是将2个数据组合成一组数据,当需要这样的需求时就可以使用pair,map就是将key和value放在一起来保存。

map的插入在成功时会返回pair<新插入值所在的迭代器,true>,插入失败会返回pair<已存在跟key等值的迭代器,false>

cpp 复制代码
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的迭代器支持正向和反向迭代遍历,遍历默认按key的升序顺序 ,因为底层是⼆叉搜索树,迭代器遍历走的中序;支持迭代器就意味着支持范围for,map支持修改value数据,不支持修改key数据,修改关键字数据,破坏了底层搜索树的结构。

cpp 复制代码
// empty (1) ⽆参默认构造 
explicit map (const key_compare& comp = key_compare(),
 const allocator_type& alloc = allocator_type());

// range (2) 迭代器区间构造 
template <class InputIterator>
 map (InputIterator first, InputIterator last,
 const key_compare& comp = key_compare(),
 const allocator_type& = allocator_type());

// copy (3) 拷⻉构造 
map (const map& x);

// initializer list (5) initializer 列表构造 
map (initializer_list<value_type> il,
 const key_compare& comp = key_compare(),
 const allocator_type& alloc = allocator_type());

map的增删查

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

map在插入的时候只会检查key,不会检查value,key相同则不会插入。

cpp 复制代码
单个数据插⼊,如果已经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[]不仅仅支持修改,还支持插⼊数据和查找数据,所以他是⼀个多功能复合接口,operator[]传key返回对应的value

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

insert插入⼀个pair对象 :1.如果key已经在map中,插入失败,则返回⼀个pair对象,返回pair对象 first是key所在结点的迭代器,second是false 2.如果key不在在map中,插入成功,则返回⼀个pair对象,返回pair对象 first是新插⼊key所在结点的迭代器,second是true 也就是说无论插⼊成功还是失败,返回pair对象的first都会指向key所在的迭代器,那么也就意味着insert插⼊失败时充当了查找的功能,正是因为这⼀点,insert可以⽤来实现 operator[]

operator[]内部实现

cpp 复制代码
mapped_type& operator[] (const key_type& k)
{
 pair<iterator, bool> ret = insert({ k, mapped_type() });
 iterator it = ret.first;
 return it->second;
}

1、如果k不在map中 ,insert会插⼊k和mapped_type默认值,同时[]返回结点中存储

mapped_type值的引⽤,那么我们可以通过引用修改返映射值。所以[]具备了插⼊+修改功能

2、如果k在map中 ,insert会插⼊失败,但是insert返回pair对象的first是指向key结点的

迭代器,返回值同时[]返回结点中存储mapped_type值的引⽤,所以[]具备了查找+修改的功能

所以我们在使用operator[]需要注意该节点是否在map中存在,这影响了operator[]实现怎么样的操作。

相关推荐
一叶之秋141210 分钟前
QT背景介绍与环境搭建
开发语言·qt
Victory_orsh20 分钟前
“自然搞懂”深度学习(基于Pytorch架构)——010203
人工智能·pytorch·python·深度学习·神经网络·算法·机器学习
java1234_小锋20 分钟前
PyTorch2 Python深度学习 - 模型保存与加载
开发语言·python·深度学习·pytorch2
CoovallyAIHub28 分钟前
突破360°跟踪极限!OmniTrack++:全景MOT新范式,HOTA指标狂飙43%
深度学习·算法·计算机视觉
煤球王子35 分钟前
学而时习之:C++中的字符串
c++
ACP广源盛139246256731 小时前
(ACP广源盛)GSV2231---DisplayPort 1.4 MST 到 HDMI 2.0/DP/Type-C 转换器(带嵌入式 MCU)
c语言·开发语言·单片机·嵌入式硬件·音视频·mst
quant_19861 小时前
【教程】使用加密货币行情接口 - 查询比特币实时价格
开发语言·后端·python·websocket·网络协议
熊猫_豆豆1 小时前
Python 写一个标准版和程序员版计算器
开发语言·python·计算器
得物技术1 小时前
得物管理类目配置线上化:从业务痛点到技术实现
后端·算法·数据分析
go_bai1 小时前
Linux--进程池
linux·c++·经验分享·笔记·学习方法