【问题标题】:Admissible type of key in map v.s. unordered_map [duplicate]地图与 s. 中可接受的键类型unordered_map [重复]
【发布时间】:2014-07-04 19:37:30
【问题描述】:

我知道unordered_map<T, int> 在从键 O(1) 检索值时会比map<T, int> 在性能方面的效率更高。

但是,我发现unordered_map<T, int> 支持的类型不如map<T, int> 支持的那么多。

例如,map<pair<int, int>, int> 可以,但unordered_map<pair<int, int>, int> 不行。

我想知道这有什么潜在的困难吗?如果关心性能,我可以使用什么数据结构来获得具有 O(1) 性能的键类型对的哈希表。

【问题讨论】:

  • 不清楚您是在问为什么它不能开箱即用,还是想知道如何让它发挥作用。到目前为止的答案都是针对后者。
  • @juanchopanza,非常好的观点。我更新以尝试解决第一个问题。
  • @merlin2011 好吧,我会解释为问“为什么std::hash 不专门用于std:pair<T, T>,其中Tstd::hash 的类型专业的:-)
  • 这是一个更好的副本:stackoverflow.com/a/7222201/390913

标签: c++ c++11 stl


【解决方案1】:

您可以定义自定义哈希函数:

#include <unordered_map>

typedef std::pair<int,int> int_pair;
class MyHashFunc {
    std::hash<int> int_hash_func;
    public:
        long operator()(const int_pair &k) const{

            return (int_hash_func(k.first) << 16) + (int_hash_func(k.second));
        }
};

int main() {
    std::unordered_map<int_pair, int, MyHashFunc> m;
    return 0;
}

【讨论】:

    【解决方案2】:

    之所以不能开箱即用是因为pair&lt;T,T&gt;类型没有定义散列函数,而unordered_map本质上是一个散列映射,所以它的键必须是可散列的 .

    unordered_map&lt;pair&lt;int, int&gt;, int&gt; 从根本上来说没有错。问题是您需要提供一个散列函数和一个比较函数来实现相等性。

    请参阅this question 了解您以&lt;pair,pair&gt; 为键的具体情况,this answer 了解有关一般情况的更多详细信息。

    【讨论】:

      【解决方案3】:

      如果您可以提供一种从pair&lt;int, int&gt; 生成哈希的方法,那么您可以使用它。

      例子:

      #include <unordered_map>
      #include <utility>
      using namespace std;
      
      struct IntPairHash
      {
         size_t operator()(pair<int, int> const& p)
         {
            // If you have a 64 bit platform where sizeof(size_t) == 64
            // and sizeof(int) == 32, you can use:
            size_t h = p.second;
            h <<= 32;
            h += p.first;
            return h;
      
            // For other platforms, a more different approach to come up with
            // a hash value for p must be devised.
         }
      };
      
      void foo()
      {
         unordered_map<pair<int, int>, int, IntPairHash> a;
      }
      

      【讨论】:

      • h &lt;&lt;= 32; - 如果sizeof(size_t) == sizeof(int) 你刚刚完全抛弃了p.second... 最好是xor(h &lt;&lt; 1) ^ (h &gt;&gt; 1) 虽然对于sizeof(size_t) == 2 * sizeof(int) 它会离开高阶位 0,在修改/合并到哈希表桶计数时不太重要。
      • @TonyD Point 做得很好。我更新了我的答案以添加该警告。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-27
      • 1970-01-01
      • 2011-12-28
      • 1970-01-01
      • 1970-01-01
      • 2021-10-31
      相关资源
      最近更新 更多