【问题标题】:Selection of map or unordered_map based on keys's type根据键的类型选择 map 或 unordered_map
【发布时间】:2012-11-10 16:17:15
【问题描述】:

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

我们在做这样的选择时不应该考虑键的数据类型吗? 因为一种数据类型(比如 int)的哈希算法可能比其他(比如字符串)更容易发生冲突。

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

【问题讨论】:

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


    【解决方案1】:

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

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

    字典顺序简单:如果你告诉我你想根据它的 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。它可能更慢(不确定),但更安全。

    【讨论】:

      【解决方案2】:

      实际上并没有像容易发生碰撞的对象这样的东西,因为这个东西取决于您使用的散列函数。假设对象不相同 - 有一些功能可用于创建要使用的信息散列函数。

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


      也就是说,还有其他问题以及为什么偏爱基于树的数据结构而不是哈希基(例如延迟和集合的大小),my answer in this thread 涵盖了一些问题。

      【讨论】:

        【解决方案3】:

        在这件事上试图太聪明是没有意义的。与往常一样,分析、比较、优化(如果有用)。涉及的因素很多——其中相当多的因素没有在标准中指定,并且会因编译器而异。有些事情在特定硬件上可能会更好或更差。如果您对这些东西感兴趣(或付费假装感兴趣),您应该更系统地了解这些东西。您可以先了解一些实际的散列函数及其特征。很难找到一个哈希函数——对于所有实际目的——不比随机但可重复的值更容易发生冲突——只是有时接近那个点比处理一些额外的冲突要慢。

        【讨论】:

          猜你喜欢
          • 2015-09-02
          • 2016-05-31
          • 2021-02-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-02-03
          • 2012-11-27
          • 1970-01-01
          相关资源
          最近更新 更多