unordered_map 简介
简介
无序映射(Unordered maps)是用于存储键值和映射值组合成的元素的关联容器,并允许基于其键快速检索各个元素。在unordered_map
中,键值通常用于唯一地标识元素,而映射值是具有与该键关联的内容的对象。键的类型和映射的值可能会有所不同。
头文件
在使用unordered_map
时,需要引入头文件:
#include < unordered_map >
内部实现
unordered_map
内部实现了一个哈希表(也叫散列表,通过把关键码值映射到Hash表中一个位置来访问记录,查找的时间复杂度可达到O(1),其在海量数据处理中有着广泛应用)。因此,其元素的排列顺序是无序的。
与map对比
map
-
优点:
-
有序性,这是
map
结构最大的优点,其元素的有序性在很多应用中都会简化很多的操作; -
红黑树,内部实现一个红黑树使得
map
的很多操作在O(lgn)的时间复杂度下就可以实现,因此效率非常的高。
-
-
缺点:空间占用率高,因为
map
内部实现了红黑树,虽然提高了运行效率,但是因为每一个节点都需要额外保存父节点、孩子节点和红/黑性质,使得每一个节点都占用大量的空间 -
应用场景:对于那些有顺序要求的问题,用
map
会更高效一些
unordered_map
- 优点:因为内部实现了哈希表,因此其查找速度非常的快
- 缺点:哈希表的建立比较耗费时间
- 应用场景:对于查找问题,
unordered_map
会更加高效一些,因此遇到查找问题,常会考虑一下用unordered_map
总结
- 内存占有率的问题就转化成红黑树 VS Hash表,还是
unordered_map
占用的内存要高; - 但是
unordered_map
执行效率要比map
高很多; - 对于
unordered_map
或unordered_set
容器,其遍历顺序与创建该容器时输入的顺序不一定相同,因为遍历是按照哈希表从前往后依次遍历的。
unordered_map的使用
unordered_map
的用法和map
是一样的,提供了 insert
,size
,count
等操作,并且里面的元素也是以pair类型来存贮的。其底层实现是完全不同的,上方已经解释了,但是就外部使用来说却是一致的。
#include <iostream>
#include <unordered_map>
#include <map>
#include <string>
using namespace std;
int main()
{
//注意:C++11才开始支持括号初始化
unordered_map<int, string> myMap={{ 5, "张大" },{ 6, "李五" }};//使用{}赋值
myMap[2] = "李四"; //使用[ ]进行单个插入,若已存在键值2,则赋值修改,若无则插入。
myMap.insert(pair<int, string>(3, "陈二"));//使用insert和pair插入
//遍历输出+迭代器的使用
auto iter = myMap.begin();//auto自动识别为迭代器类型unordered_map<int,string>::iterator
while (iter!= myMap.end())
{
cout << iter->first << "," << iter->second << endl;
++iter;
}
//查找元素并输出+迭代器的使用
auto iterator = myMap.find(2);//find()返回一个指向2的迭代器
if (iterator != myMap.end())
cout << endl<< iterator->first << "," << iterator->second << endl;
system("pause");
return 0;
}
练习
236. 二叉树的最近公共祖先
方法二:存储父节点
思路
我们可以用哈希表存储所有节点的父节点,然后我们就可以利用节点的父节点信息从 p
结点开始不断往上跳,并记录已经访问过的节点,再从 q
节点开始不断往上跳,如果碰到已经访问过的节点,那么这个节点就是我们要找的最近公共祖先。
算法
-
从根节点开始遍历整棵二叉树,用哈希表记录每个节点的父节点指针。
-
从
p
节点开始不断往它的祖先移动,并用数据结构记录已经访问过的祖先节点。 -
同样,我们再从
q
节点开始不断往它的祖先移动,如果有祖先已经被访问过,即意味着这是p
和q
的深度最深的公共祖先,即 LCA 节点。
class Solution {
public:
unordered_map<int, TreeNode*> fa;
unordered_map<int, bool> vis;
void dfs(TreeNode* root){
if (root->left != nullptr) {
fa[root->left->val] = root;
dfs(root->left);
}
if (root->right != nullptr) {
fa[root->right->val] = root;
dfs(root->right);
}
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
fa[root->val] = nullptr;
dfs(root);
while (p != nullptr) {
vis[p->val] = true;
p = fa[p->val];
}
while (q != nullptr) {
if (vis[q->val]) return q;
q = fa[q->val];
}
return nullptr;
}
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/solution/er-cha-shu-de-zui-jin-gong-gong-zu-xian-by-leetc-2/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
参考资料
[1] map和unordered_map的差别和使用
[2] Unordered Map - C++ Reference
[3] 二叉树的最近公共祖先 - 力扣(LeetCode)