【问题标题】:Find bucket in unordered_map from hash without a key从没有键的哈希中查找 unordered_map 中的存储桶
【发布时间】:2012-10-15 16:13:27
【问题描述】:

我正在使用 std::unordered_map。我有一个哈希值和一种方法来确定给定的候选键是否是我正在寻找的键,但我没有实际的键。我想查找与哈希值对应的存储桶,并遍历该存储桶中的每个元素以查看它是否是我要查找的元素。不幸的是,函数 std::unordered_map::bucket(x) 需要 x 作为键。真的没有办法在不先构造key的情况下从hash值中获取bucket吗?

您无需回答问题的详细信息:我可以构造密钥,但在没有冲突的常见情况下,这将比仅检查我在其中找到的单个候选人需要更长的时间桶是正确的。我的负载因子很低,因此碰撞很少,即使对于碰撞,完整的哈希值也不太可能匹配,因此不匹配很快就会被确定为不匹配。我之所以关心这一点,是因为我已经通过分析器确定密钥构建需要大量时间 - 有很多查找,每次查找都需要构建一个密钥。

更多细节,你真的不需要回答这个问题:键是整数向量,我的查询是两个向量的和。检查给定向量 V 是否是两个向量 A 和 B 的总和比将两个向量求和为第三个向量 C=A+B 然后将 C 与 V 进行比较更快。我能够确定A+B 没有计算实际的向量 A+B,因为我存储了这些向量的哈希值,并且我的哈希函数 f 具有 f(A+B)=f(A)+f(B) 的属性。所以我只是将两个存储的哈希值相加得到总和的哈希值。我已经确保保留一个备用向量,以便构建密钥不需要内存分配,但添加向量的代码仍然需要大量时间。

【问题讨论】:

  • 不,做不到。如果你只有哈希,你无法真正判断你是否找到了正确的,所以这个问题是不可能的,除非你有一个密钥。
  • 您能出示您的unordered_map 的声明吗?具体来说,Key 使用什么类?
  • 你为什么要在桶里到处挖?
  • @JohnDibling:我认为他在这一点上的解释很清楚。
  • @MooingDuck 我相信哈希值唯一确定了一个桶,所以应该可以从哈希值中分辨出我想要哪个桶。如果我们计算 C=A+B,那么我们必须将 C 存储在内存中,当我们检查 C==V 时,我们必须再次将 C 加载到 CPU 的寄存器中。如果我们直接检查 A+B==V,那么就可以避免存储和加载 C 的顺序——我们可以计算 x=A[i]+B[i],然后在 x 仍然存在时立即检查 x==V[i]存储在 CPU 寄存器中。

标签: c++ stl c++11


【解决方案1】:

你无法避免构造一个键,但你可以避免构造整个键

例如,假设您有一个密钥类VectorKey,它封装了std::vector,并缓存了计算得到的哈希码。进一步假设您提供了HashKeyEqual 的实现,它们从VectorKey 访问缓存的哈希码,并比较封装的向量是否相等。您可以定义VectorKey 的构造函数,它始终构造一个空的std::vector,并将缓存的哈希码设置为传递给构造函数的值:

class VectorKey{
    int cached_hash;
    std::vector<int> key;
public:
    VectorKey(const std::vector<int>& _key)
    :    key(_key)
    ,    cached_hash(calc_hash(_key)) {
    }
    // *** This is the centerpiece of the solution: *** 
    // *** this constructor effectively lets you access *** 
    // *** a bucket with nothing more than a hash code. *** 
    VectorKey(int hash)
    :    cached_hash(hash) {
    }
    // More code goes here for getting cached_hash
    // and also for checking equality
private:
    int calc_hash(const std::vector<int>& _key) {
         // calculate the hash code based on the vector
    }
};

使用这样的密钥类,您可以通过构造假密钥来快速找到存储桶:

size_type bucketIndex = myHashMap.bucket(VectorKey(precalculated_hash));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-17
    • 1970-01-01
    • 1970-01-01
    • 2016-06-17
    • 1970-01-01
    • 1970-01-01
    • 2015-07-09
    • 1970-01-01
    相关资源
    最近更新 更多