为啥 unordered_map 需要散列而不是地图?
Posted
技术标签:
【中文标题】为啥 unordered_map 需要散列而不是地图?【英文标题】:Why hashing is required for unordered_map and not in map?为什么 unordered_map 需要散列而不是地图? 【发布时间】:2021-10-14 07:55:54 【问题描述】:我是 C++ 新手,我知道 unordered_map 使用散列,而 map 使用红黑树。我很困惑为什么 unordered_map 需要散列而不在 map 中。是什么原因?
#include <bits/stdc++.h>
using namespace std;
struct hash_pair
template <class T1, class T2>
size_t operator()(const pair<T1, T2>& p) const
auto hash1 = hash<T1>(p.first);
auto hash2 = hash<T2>(p.second);
return hash1 ^ hash2;
;
int main()
unordered_map<pair<int, int>, int, hash_pair> hmap1;
hmap1[1,1]=2;
if (hmap1.find(1,1)!=hmap1.end()) cout<<"Value found :"<<hmap1[1,1]<<endl;
if (hmap1.find(0,0)==hmap1.end()) cout<<"Value not found"<<endl;
map<pair<int, int>, int> hmap2;
hmap2[2,2]=4;
if (hmap2.find(2,2)!=hmap2.end()) cout<<"Value found :"<<hmap2[2,2]<<endl;
if (hmap2.find(0,0)==hmap2.end()) cout<<"Value not found"<<endl;
return 0;
输出:
找到的值:2
未找到值
找到的值:4
未找到值
【问题讨论】:
你知道什么是红黑树,它是如何工作的吗? @NathanOliver 是的,我知道它是如何工作的。有什么我想念的 看来您不了解 RB 树的工作原理,否则,您会立即明白为什么std::map
不需要哈希函数。
必须链接到Why should I not #include <bits/stdc++.h>? 和Why is “using namespace std;” considered bad practice?。它们一起放大了彼此的最坏影响,并且可以轻松地将程序变成怪异的雷区。谨慎使用,当您的代码有问题时,它们应该是最先被删除的东西。
如果您想从编码竞赛网站学习 C++,请不要这样做。教学不是他们的目的,因此他们真的很烂。节省自己的时间并获得couple good books。你会为自己节省很多时间。
【参考方案1】:
原因很简单:std::map
在其红黑树中查找一个项目,从树的根开始递归地向下移动,将树的每个节点的项目与关键项目进行比较(使用<
运算符),并使用比较的结果来决定递归到哪个子节点,直到它最终到达它正在寻找的节点并返回结果(或者直到它到达一个叶子节点节点没有遇到请求的密钥,在这种情况下它将返回错误)。在这个过程中,任何时候都不需要计算任何东西的哈希码。
另一方面,std::unordered_map
不使用树型数据结构。相反,它使用散列来计算它应该在其内部数据数组中的哪个位置查找指定的键。为此,它需要能够计算该密钥的哈希码;然后它可以计算该哈希码的模以获得一个数组索引以开始查找。
【讨论】:
以上是关于为啥 unordered_map 需要散列而不是地图?的主要内容,如果未能解决你的问题,请参考以下文章
Python中字典数据类型,字典.values()可以进行遍历,为啥不能通过角标进行获取元素?
对于 unordered_map,对于具有 3 个无符号字符和一个 int 的结构,啥是好的散列函数?
如何在删除元素时防止重新散列 std::unordered_map?