根据键的类型选择map或unordered_map

时间:2012-11-10 16:17:16

标签: c++ algorithm boost data-structures c++11

一个普遍问的问题是我们是否应该使用unordered_map或map来加快访问速度。 这个问题最常见(相当古老)的答案是: 如果您想直接访问单个元素,请使用unordered_map,但如果您想迭代元素(最有可能以排序方式),请使用map。

在做出这样的选择时,我们不应该考虑密钥的数据类型吗? 由于一个dataType(比如int)的哈希算法可能比其他(例如字符串)更容易发生冲突。

如果是这种情况(哈希算法很容易发生冲突),那么我可能会使用map甚至直接访问,因为在这种情况下O(1)常量时间(可能是大量输入的平均值)即使对于相当大的N值,unordered_map map也要超过lg(N)。

3 个答案:

答案 0 :(得分:3)

你提出了一个很好的观点......但你正在关注错误的部分。

问题不在于密钥的类型本身,而在于用于导出该密钥的哈希值的哈希函数。

词典排序简单:如果你告诉我你想根据它的3个字段订购一个结构(并且他们已经支持自己排序)那么我只会写:

bool operator<(Struct const& left, Struct const& right) {
    return boost::tie(left._1,  left._2,  left._3)
         < boost::tie(right._1, right._2, right._3);
}

我完成了!

但编写哈希函数困难。你需要一些关于数据分布的知识(统计数据),你可能需要防止特制的攻击等等......老实说,我不希望很多人能够制作出好的哈希函数。但最糟糕的是,组成也很难!给定两个独立字段,将它们的哈希值 right 组合起来很难(提示:boost::hash_combine)。

所以,的确,如果您不知道自己在做什么,并且正在处理用户制作的数据,那么只需坚持map即可。它可能更慢(不确定),但它更安全。

答案 1 :(得分:2)

没有易碰撞对象这样的东西,因为这个东西依赖于你使用的哈希函数。假设对象不相同 - 有一些功能可用于创建要使用的信息散列函数。

假设您对数据有一些了解 - 并且您知道某些哈希函数h1()可能会发生很多冲突 - 那么您应该找到并使用不同的哈希函数h2()更适合这项任务。


尽管如此,还有其他问题也是为什么要优先于基于树的数据结构而不是哈希基础(例如延迟和集合的大小),有些问题由my answer in this thread覆盖。

答案 2 :(得分:1)

没有必要试图对此过于聪明。与往常一样,配置文件,比较,优化,如果有用。涉及的因素很多 - 很多因素都没有在标准中指定,并且会因编译器而异。有些东西可能在特定硬件上更好或更差。如果你对这些东西感兴趣(或付出假装),你应该更系统地了解这些东西。您可以从了解实际哈希函数及其特征开始。很难找到一个哈希函数,它具有 - 出于所有实际目的 - 不再具有碰撞倾向而不是随机但可重复的值 - 它只是有时它接近它的速度较慢这一点,而不是处理一些额外的碰撞。