在std :: map和std :: unordered_map之间进行选择

时间:2010-10-10 23:29:27

标签: c++ c++11 hash map unordered-map

现在stdunordered_map中有一个真实的哈希映射,为什么(或何时)我仍然希望在系统中使用优质旧map而不是unordered_map它确实存在?是否有任何我无法立即看到的明显情况?

5 个答案:

答案 0 :(得分:105)

作为already mentionedmap允许以排序方式迭代元素,但unordered_map不允许。这在许多情况下非常重要,例如显示集合(例如地址簿)。这也体现在其他间接方式中:(1)从find()返回的迭代器开始迭代,或者(2)存在lower_bound()等成员函数。

此外,我认为最差情况 搜索复杂性存在一些差异。

  • 对于map,它是O(lg N)

  • 对于unordered_map,它是O(N)[当哈希函数不好导致太多哈希冲突时,会发生 may 。]

    < / LI>

同样适用于最坏情况 删除复杂性。

答案 1 :(得分:85)

除了上面的答案,你还应该注意,仅仅因为unordered_map是恒定速度(O(1))并不意味着它比maplog(N)更快}})。常数可能大于log(N),特别是因为N受限于2 32 (或2 64 )。

因此,除了其他答案(map维护顺序和哈希函数可能很困难),map可能更高效。

例如,在我为blog post运行的程序中,我看到VS10 std::unordered_map的速度比std::map慢(尽管boost::unordered_map比两者都快)。

Performance Graph

注意第3到第5栏。

答案 2 :(得分:24)

这是由于Google的Chandler Carruth在CppCon 2014 lecture

std::map(被许多人认为)对于面向性能的工作没有用处:如果你想要O(1)-amortized访问,使用适当的关联数组(或缺少一个,{{1 }});如果您想要排序顺序访问,请使用基于向量的内容。

此外,std::unorderded_map是一棵平衡的树;你不得不经常穿越它,或者重新平衡它。这些分别是cache-killer和cache-apocalypse操作......所以只对std::map说“NO”。

您可能对有效哈希映射实现的this SO question感兴趣。

(PS - std::map缓存不友好,因为它使用链接列表作为存储桶。)

答案 3 :(得分:21)

我认为很明显,您需要使用std::map以排序顺序迭代地图中的项目。

当您更喜欢编写比较运算符(直观)而不是散列函数(通常非常不直观)时,您也可以使用它。

答案 4 :(得分:7)

假设您有非常大的键,也许是大字符串。要为大字符串创建哈希值,您需要从头到尾遍历整个字符串。至少需要线性时间到密钥的长度。但是,当您仅使用键的find运算符搜索二叉树时,每次找到不匹配时,每个字符串比较都会返回。对于大字符串,这通常很早。

此推理可应用于std::unordered_mapstd::map的{​​{1}}功能。如果密钥的性质使得生成散列(在std::unordered_map的情况下)花费的时间比使用二进制搜索找到元素的位置花费的时间长(在std::map的情况下) ),在std::map中查找密钥应该更快。很容易想到会出现这种情况的情况,但我相信它们在实践中很少见。