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

相关推荐
oioihoii7 分钟前
C++11 forward_list 从基础到精通:原理、实践与性能优化
c++·性能优化·list
满分观察网友z11 分钟前
开发者的“右”眼:一个树问题如何拯救我的UI设计(199. 二叉树的右视图)
算法
m0_6873998415 分钟前
写一个Ununtu C++ 程序,调用ffmpeg API, 来判断一个数字电影的视频文件mxf 是不是Jpeg2000?
开发语言·c++·ffmpeg
爱上语文25 分钟前
Redis基础(5):Redis的Java客户端
java·开发语言·数据库·redis·后端
A~taoker31 分钟前
taoker的项目维护(ng服务器)
java·开发语言
萧曵 丶34 分钟前
Rust 中的返回类型
开发语言·后端·rust
hi星尘1 小时前
深度解析:Java内部类与外部类的交互机制
java·开发语言·交互
看到我,请让我去学习1 小时前
Qt编程-qml操作(js,c++,canvas)
开发语言·qt
橘子编程1 小时前
Python-Word文档、PPT、PDF以及Pillow处理图像详解
开发语言·python
森焱森1 小时前
无人机三轴稳定化控制(1)____飞机的稳定控制逻辑
c语言·单片机·算法·无人机