为什么复合数字不适合除法散列



这是我关于stackflow的第一个问题。正如你所知,我是学习算法和数据结构的新手。

当使用除法创建哈希函数(即h(k)=k mod m)时,建议(例如CLRS)使用不太接近除数m的2次方的素数。有人能向我解释为什么选择m作为复合数是不好的吗?

考虑如果m是偶数并且所有k值都是偶数的情况。然后,散列值也将全部为偶数。

例如,考虑m=6散列偶数值的情况:

Input values:  0, 2, 4, 6, 8, 10, 12, 14, 16, ...
Hash values:   0, 2, 4, 0, 2,  4,  0,  2,  4, ...

如果使用这些散列值作为表的索引,那么表的一半将未使用。另一方面,如果m是素数,则即使输入值都有一个公共因子,也会得到哈希值的均匀分布。

考虑相同的输入值,但m=7:

Input values:  0, 2, 4, 6, 8, 10, 12, 14, 16, ...
Hash values:   0, 2, 4, 6, 1,  3,  5,  0,  2, ...

尽管输入值都是偶数,但哈希值仍然均匀分布在[0..6]上。

总之,如果m是素数,那么即使所有输入值都可以被一个公共素数整除(而不是m),你仍然会得到哈希值的均匀分布。

如果你知道散列函数,那么你总是可以生成一组完美的输入数据,这会让散列函数表现得很糟糕。没有"通用最佳"散列函数。但总有一组最好的输入数据和一组最差的输入数据。

一个好的散列函数被期望将大集合X的任何子集映射到较小的输出集合Y,在集合Y上具有最小且公平的冲突分布。

作为推论,如果不知道哈希函数将被视为"好函数"的数据集,就无法预测哈希函数是否是好函数。

关于在不知道散列值的情况下使用素数而不是复数的建议,并不比声称87654321是散列的最佳模数更好。

如果你想散列素数或斐波那契数,那么关于使用素数模、复合模或2的幂的建议是无关紧要的。

如果你想对复合数进行成对共素散列,那么输入集每个元素的复合模共素就是一个"好"选择的候选者。素数模大于输入集所有元素的最大因子是另一个"好"的选择。

如果你的输入集是一个区间内的稀疏整数集,数字之间的区间呈高斯分布,那么模数的"最佳"选择是一个能最大限度地减少gcd(模数,输入数据)出现的数字!=1.选择素数作为模更有可能发生这种情况。

这就是建议使用素数的原因。

最新更新