我正在使用std :: unordered_map。我有一个哈希值和一种方法来确定给定的候选键是否是我正在寻找的键,但我没有实际的键。我想查找与哈希值对应的存储桶,并浏览该存储桶中的每个元素,看看它是否是我要查找的元素。不幸的是,函数std :: unordered_map :: bucket(x)需要x作为键。如果没有先构建密钥,是否真的无法从哈希值中获取存储桶?
您不需要回答问题的详细信息:我可以构建密钥,但在没有冲突的常见情况下,这将花费更长的时间,而不仅仅是检查我找到的单个候选人水桶是正确的。我的负载系数很低,因此冲突很少,即使是碰撞,完整的哈希值也不太可能匹配,因此很快就会确定非匹配不匹配。我关心这个因为我已经确定了一个分析器,关键构造需要花费大量的时间 - 有很多查找,每次查找都需要构建一个密钥。
更多细节,你真的不需要回答这个问题:键是整数的向量,我的查询是两个向量的总和。检查给定向量V是两个向量A和B的总和比将两个向量加到第三个向量C = A + B然后将C与V进行比较更快。我能够确定哈希值A + B没有计算实际矢量A + B,因为我存储了这些矢量的哈希值,而我的哈希函数f具有f(A + B)= f(A)+ f(B)的特性。所以我只需添加两个存储的哈希值来获得总和的哈希值。我已经确保保留一个备用向量,以便构造一个密钥不需要内存分配,但添加向量的代码仍然需要花费大量的时间。
答案 0 :(得分:9)
您无法避免构建密钥,但可以避免构建整个密钥。
例如,假设您有一个密钥类VectorKey
,它封装了std::vector
,并缓存计算出的哈希码。进一步假设您提供了Hash
和KeyEqual
的实现,这些实现从您的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));