除了生成大量值并查看值的分布外,您还知道如何评估哈希函数的效率? 效率我的意思是哈希函数生成的密钥均匀分布。有没有办法在没有实际测试实际值的情况下证明这一点?
答案 0 :(得分:4)
散列函数在被散列的数据的上下文中只是
考虑两个数据集:
设置1
1, 3, 6, 2, 7, 9, 5, 8, 4
设置2
65355, 96424664, 86463624, 133, 643564, 24232, 88677, 865747, 2224
一组的良好散列函数(即第1组的mod 10)不会产生碰撞,可以看作是该数据集的完美散列
然而将其应用于第二组并且到处都有碰撞
Hash = (x * 37) mod 256
对于第二组更好,但可能不太适合第一组...特别是在分割哈希时,例如少量的桶。
你可以做的是评估你希望你的函数必须处理的随机数据的哈希......但这是假设......
过早优化是在之前寻找完美的哈希函数,你有足够的实际数据来作为评估的依据。
在重新散列的成本变得无法改变你的散列函数之前,你应该得到足够的数据
让我们假设我们正在寻找一个生成输入数据的8位散列的散列函数。让我们进一步假设散列函数应该采用不同长度的字节流。
如果假设字节流中的字节均匀分布,我们可以对不同的哈希函数进行一些评估。
int hash = 0;
for (byte b in datastream) hash = hash xor b;
此函数将为指定的数据集生成均匀分布的哈希值,因此在此上下文中将是一个很好的哈希函数。如果您不明白为什么会这样,那么您可能会遇到其他问题。
int hash = 37;
for (byte b in datastream hash = (31 * hash + b) mod 256;
此函数将为指定的数据集生成均匀分布的哈希值,因此在此上下文中将是一个很好的哈希函数。
现在让我们将数据集从0到255范围内的随机数的可变长度字符串更改为包含编码为US-ASCII的英文句子的可变长度字符串。
然后,XOR是一个糟糕的哈希,因为输入数据永远不会设置第8位,因此只会产生0-127范围内的哈希值,因为这个字母有一些“热”值的可能性更高英语单词的频率和异或的抵消效果。
这对素数作为散列函数仍然相当不错,因为它使用全输出范围,而素数初始偏移与不同的素数乘数相结合往往会将值扩散出去。但由于英语语言结构的原因,碰撞仍然很弱......只能用真实数据进行测试才能显示出来。