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\[\]实现怎么样的操作。

相关推荐
地平线开发者7 小时前
profiler debug 工具用法与高一致性策略
算法·自动驾驶
编程大师哥7 小时前
匿名函数 lambda + 高阶函数
java·python·算法
isyangli_blog7 小时前
OpenDayLight (Carbon 版本) 启动与组件安装
开发语言·php
vb2008118 小时前
FastAPI APIRouter
开发语言·python
Benszen8 小时前
KVM虚拟化解决方案
开发语言·perl
会编程的土豆8 小时前
Go 语言反射(Reflection)详解
开发语言·后端·golang
東雪木8 小时前
多线程与并发编程 专属复习笔记
java·开发语言·笔记·java面试
我叫袁小陌8 小时前
算法解题思路指南
算法
MC皮蛋侠客8 小时前
C++17 多线程系列(五):C++17 并行算法——从串行到并行的零成本迁移
c++·多线程
地平线开发者8 小时前
Conv+BN+Add+ReLU 融合机制简介
算法·自动驾驶