我正在挖掘.NET的Dictionaries实现,发现了一个我很好奇的函数:HashHelpers.GetPrime
。
它所做的大部分工作都非常简单,它会查找高于某个最小值的素数,并将其作为参数传递给它,显然是出于在哈希表结构中用作多个存储桶的特定目的。但是有一个神秘的部分:
if (HashHelpers.IsPrime(j) && (j - 1) % 101 != 0)
{
return j;
}
(j - 1) % 101 != 0
检查的目的是什么?也就是说,为什么我们显然想要避免使用多于101倍的数量的桶?
答案 0 :(得分:6)
comments解释得非常好:
'InitHash'基本上是经典DoubleHashing的实现 (见http://en.wikipedia.org/wiki/Double_hashing)
1)唯一的“正确性”要求是“增量”用于 探究一个。不为零b。相对于桌子大小的素数 “HASHSIZE”。 (这是为了确保您探测中的所有条目 在你“包装”并访问已探测的条目之前的表格
2)因为 我们选择表格大小为素数,我们只需要确保 增量为0< incr< HASHSIZE
因此这个函数可以工作:Incr = 1 +(种子%(hashSize-1))
虽然这适用于“均匀分布”的键,但在实践中, 不均匀性很常见。特别是在实践中我们可以看到 “大多是顺序的”,你可以获得“打包”的长串密钥。 为避免不良行为,您希望增量为 “大”甚至是“小”值(因为小值往往会发生 更多在实践中)。因此,我们将“种子”乘以一个数字 这些小值更大(并且不会伤害大值)。 我们挑选了 HashPrime(101)因为它是素数,如果'hashSize-1'不是 HashPrime的多个(在GetPrime中强制执行),然后incr有 从1到hashSize-1的每个值的潜力。选择是 很随意。