现在std
在unordered_map
中有一个真实的哈希映射,为什么(或何时)我仍然希望在系统中使用优质旧map
而不是unordered_map
它确实存在?是否有任何我无法立即看到的明显情况?
答案 0 :(得分:105)
作为already mentioned,map
允许以排序方式迭代元素,但unordered_map
不允许。这在许多情况下非常重要,例如显示集合(例如地址簿)。这也体现在其他间接方式中:(1)从find()
返回的迭代器开始迭代,或者(2)存在lower_bound()
等成员函数。
此外,我认为最差情况 搜索复杂性存在一些差异。
对于map
,它是O(lg N)
对于unordered_map
,它是O(N)[当哈希函数不好导致太多哈希冲突时,会发生 may 。]
同样适用于最坏情况 删除复杂性。
答案 1 :(得分:85)
除了上面的答案,你还应该注意,仅仅因为unordered_map
是恒定速度(O(1)
)并不意味着它比map
(log(N)
更快}})。常数可能大于log(N)
,特别是因为N
受限于2 32 (或2 64 )。
因此,除了其他答案(map
维护顺序和哈希函数可能很困难),map
可能更高效。
例如,在我为blog post运行的程序中,我看到VS10 std::unordered_map
的速度比std::map
慢(尽管boost::unordered_map
比两者都快)。
注意第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_map
和std::map
的{{1}}功能。如果密钥的性质使得生成散列(在std::unordered_map
的情况下)花费的时间比使用二进制搜索找到元素的位置花费的时间长(在std::map
的情况下) ),在std::map
中查找密钥应该更快。很容易想到会出现这种情况的情况,但我相信它们在实践中很少见。