map和multimap参考文档
map和multimap参考文档https://legacy.cplusplus.com/reference/map/
map类的介绍
- map的声明如下,Key就是map底层关键字的类型,T是map底层T的类型。但要注意:map的 key 与 T 是封装在std::pair<Key,T>存储键值对应数据。这就类似于封装的map中又将封装key 与 T 到pair中;
- set默认要求Key支持小于比较,如果不支持或者需要的话可以自行实现仿函数传给第⼆个模版参数。
- map底层存储数据的内存是从空间配置器申请的。⼀般情况下,我们都不需要传后两个模版参数。
- map底层是用红黑树实现,增删查改效率是 O(logN) (利用的是AVL),迭代器遍历是走的中序,所以是按key有序顺序遍历的。
pair类型介绍
template <class T1, class T2>
struct pair {
T1 first;
T2 second;
//类型() 就是默认类型的构造
pair(const T1& t1 = T1(), const T2& t2 = T2())
:first(t1)
, second(t2)
{}
};
template<class T1, class T2>
inline pair<T1, T2> make_pair(const T1& t1, const T2& t2)
{
return (pair<T1, T2>(t1, t2));
};
注意:
- make_pair(c++11才支持) 类似于一个函数,返回值是pair 类型的;这种函数十分好用,在传参要用到pair时就可以 用make_pair 结构;
map<int, int> m1;
m1.insert(make_pair(1, 1));
- map底层的红⿊树节点中的数据,使⽤pair<Key, T>存储键值对数据。
map的构造
- map的支持双向迭代器,遍历默认按key的升序顺序(仿函数可以自组定义)
- 因为底层是⼆叉搜索树,迭代器遍历⾛的中序;支持迭代器就意味着支持范围for。
- map支持修改value数据,不支持修改key数据,修改关键字数据,破坏了底层搜索树的结构。
map的构造这里关注以下几个接口(其他可以自主查看map参考文档):
// 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<string, string> dict = { { "left", "左" }, { "right", "右" }, { "string", "字符串" }, { "insert", "插入" } };
map<string, string> dict{ { "left", "左" }, { "right", "右" }, { "string", "字符串" }, { "insert", "插入" } };
map<int, int> v1{{ 1, 2 }, { 3, 4 }, { 5, 6 } };
map<int, int> m3(v1.begin(), v1.end());
map的增删查
- map增接口,插入的pair键值对数据,跟set所有不同,但是查和删的接口只用关键字key跟set是完全类似的。而且关键字key是不能修改的;
- 不过find返回iterator,不仅仅可以确认key在不在,还找到key映射的value,同时通过迭代还可以修改value。
下面的和set极其相似,具体的在上一篇set讲咯,这里就不重复了;
// 单个数据插⼊,如果已经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中,控制随机指针会⾮常简单⽅便,这⾥体现了map在解决⼀些问题时的价值,完全是降维打击。
. - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/copy-list-with-random-pointer/
用c语言写
struct Node* copyRandomList(struct Node* head) { struct Node* cur = head; while(cur) { //自主创立映射 struct Node* copy = (struct Node*)malloc(sizeof(struct Node)); copy->val = cur->val; copy->next = cur->next; cur->next = copy; cur = copy->next; } cur = head; while(cur) { //控制 random 的指向 if(cur->random == NULL) { cur->next->random = NULL; } else { cur->next->random = cur->random->next; } cur = cur->next->next; } struct Node* copytail = NULL; struct Node* copyhead = NULL; cur = head; while(cur) { if(copytail == NULL) { copytail = copyhead = cur->next; }else{ copytail->next = cur->next; copytail = copytail->next; } cur = cur->next->next; } return copyhead; }
{原结点,拷⻉结点}建⽴映射关系放到map中:
class Solution { public: Node* copyRandomList(Node* head) { map<Node*, Node*> m1; Node* cur = head; Node* copyhead = nullptr; Node* copytail = nullptr; while(cur) { if(copyhead == nullptr) { copyhead = copytail = new Node(cur->val); }else{ copytail->next = new Node(cur->val); copytail = copytail->next; } m1[cur] = copytail; cur = cur->next; } cur = head; Node* copy = copyhead; while(cur) { if(cur->random == nullptr) { copy->random = nullptr; }else{ copy->random = m1[cur->random]; } copy = copy->next; cur = cur->next; } return copyhead; } };