目录
[Part1. map / multimap 核心接口](#Part1. map / multimap 核心接口)
[Part1.1. 基础接口](#Part1.1. 基础接口)
[Part1.2. map独有接口](#Part1.2. map独有接口)
[Part1.3. 接口insert() 的特殊返回值:pair<迭代器, bool>](#Part1.3. 接口insert() 的特殊返回值:pair<迭代器, bool>)
[Part1.4. 容器multimap 与map的不同之处](#Part1.4. 容器multimap 与map的不同之处)
[Part1.5. 容器map在算法题中的使用](#Part1.5. 容器map在算法题中的使用)
[Part2. AVL树介绍与使用](#Part2. AVL树介绍与使用)
[Part2.1. 平衡判定规则](#Part2.1. 平衡判定规则)
[Part2.2. AVL插入完整流程](#Part2.2. AVL插入完整流程)
[Part2.3. 旋转调整](#Part2.3. 旋转调整)
[Part3. 结语](#Part3. 结语)
前言
map作为C++很重要的容器,同时AVL树也是经典的数据结构,了解他们的构成是必要的,接下来,跟随小编的视角来看看这两个的介绍和基本的使用吧。
let's go!!!!!!!!!
Part1. map / multimap 核心接口
Part1.1. 基础接口
<1> erase(it/key):支持迭代器删除、按key批量删除
<2> swap()
<3> clear()
<4> find(key):返回目标键的迭代器,不存在返回 end() (multimap返回中序遍历第一个出现的)
<5> count(key):返回容器中该 key 存在的元素个数
Part1.2. map独有接口
<1> mapped_type& operator\[\] (const key_type& k);
<2> 功能:传入key,返回对应value引用。
<3> 关键特性:++若传入的key不存在,会自动插入该键,默认构造空value后返回。++
<4> 底层逻辑:
cpppair<iterator, bool> ret = insert({k, mapped_type()});//通过insert插入 再通过它的返回值返回value iterator it = ret.first; return it->second;
Part1.3. 接口insert() 的特殊返回值:pair<迭代器, bool>
返回值含义:
<1> 插入成功(容器无重复key):返回新插入节点迭代器 + true
<2> 插入失败(key已存在):返回原有同key节点迭代器 + false
拓展用法:可通过返回的布尔值,实现类似find的查找判断逻辑。
Part1.4. 容器multimap 与map的不同之处
<1> 不支持 operator\[\]
同一key可存储多条value,下标无法确定返回哪一个value,直接禁用。<2> 批量同key查找:equal_range(key)
返回 pair<iterator, iterator>:1.++第一个迭代器:第一个大于等于key的节点(lower_bound)++
2. ++第二个迭代器:第一个大于key的节点(upper_bound)++
两个迭代器围成区间 [it1, it2),包含当前key全部元素,是multimap遍历同key数据的高效方案。
Part1.5. 容器map在算法题中的使用
cppNode* copyRandomList(Node* head) { //关键在于通过map建立新节点和原节点之间的映射关系 if(head==nullptr) { return nullptr; } map<Node*,Node*> aaa; Node* _head=new Node(head->val);; Node* start=head; Node* _start=_head; while(start->next!=nullptr) { _start->next=new Node(start->next->val); start=start->next; _start=_start->next; } _start=_head; start=head; while(start!=nullptr) { aaa.insert({start,_start}); start=start->next; _start=_start->next; } _start=_head; start=head; while(_start!=nullptr) { auto it=aaa.find(start->random); if(it!=aaa.end()) _start->random=it->second; else _start->random=nullptr; _start=_start->next; start=start->next; } return _head; }
题目链接:138. 随机链表的复制 - 力扣(LeetCode)
cppbool cmp(pair<string,int> a,pair<string,int> b) { if(a.second!=b.second) { return a.second>b.second; } else { return a.first<b.first; } } class Solution { public: //关键在于我们要用一个比较器来比较在出现次数相同的情况下 根据字典序来排序 vector<string> topKFrequent(vector<string>& words, int k) { map<string,int> aaa; for(auto s:words) { aaa[s]++; } vector<pair<string,int>> bbb(aaa.begin(),aaa.end()); sort(bbb.begin(),bbb.end(),cmp);/stable_sort(bbb.begin(),bbb.end(),kv());//因为上面这个map已经对字典序排序过一次了 这里用稳定排序就不用在用函数来单独处理出现次数相同的情况了 vector<string> ans; for(int i=0;i<k;i++) { ans.push_back(bbb[i].first); } return ans; } };
Part2. AVL树介绍与使用
Part2.1. 平衡判定规则
<1> AVL树要求:任意节点左右子树高度差绝对值 ≤ 1
<2> 平衡因子公式:平衡因子 = 右子树高度 - 左子树高度
<3> 合法取值:-1、0、1
Part2.2. AVL插入完整流程
<1> 新增节点,完成二叉搜索树插入;
<2> 向上回溯更新路径上其父亲节点的平衡因子;
<3> 若节点平衡因子超出 -1,1,判定失衡,旋转调整(调整后不用向上调整了);
<4> 若节点平衡因子为1/-1,说明调整前是平衡的,现在不平衡了,高度改变,继续向上调整。
<5> 若节点平衡因子为0,说明平衡,高度不变,停止向上调整。
<6> 若遇到根节点,停止向上调整。
代码实现:
cppbool insert(const std::pair<k, v>& kv) { if (_root == nullptr) { _root(kv); return; } Node* cur = _root; Node* parent = nullptr; while (cur) { if (cur->_kv.first > kv.first) { parent = cur; cur = cur->_left; } else if(cur->_kv.first < kv.first) { parent = cur; cur = cur->_right; } else { return false; } } cur = new Node(kv); if (parent->_kv.first > kv.first) { parent->_left = cur; } else { parent->_right = cur; } cur->_parent = parent; while (parent) { if (cur == cur->_parent->_left) { cur->_parent->_bf--; } else { cur->_parent->_bf++; } if (cur->_parent->_bf == 0) { break; } else if (cur->_parent->_bf == 1 || cur->_parent->_bf == -1) { cur = cur->_parent; } else if(cur->_parent->_bf == 2 || cur->_parent->_bf == -2) { break; } else { assert(false); } } return true; }
Part2.3. 旋转调整
失衡分4类,通过单次/双旋转降低子树高度,重新满足AVL平衡规则:
<1> 右单旋 <2> 左单旋 <3> 左右双旋 <4> 右左双旋
右单旋抽象图解:
(左单旋与之相似)
具体的,当h=2 时共有 3×3×4=36 种子树组合,h=3 时组合数达6120种,但我们只要掌握抽象图就好。
Part3. 结语
上面我们介绍了map和AVL的基本情况,接下来小编还会有更多文章关于这个的,也请敬请期待~
最后,祝大家可以:春风得意马蹄疾,一日看尽长安花!最后的最后,要是觉得本文还可以的话,可以点点赞,关注小编一波,谢谢大家!~



