这是我关于stackflow的第一个问题。如您所知,我是学习算法和数据结构的新手。
当使用除法方法创建一个散列函数(即h(k)= k mod m)时,建议(例如通过CLRS)使用一个素数不能太接近2的幂数除数m 。有人可以向我解释为什么选择m为复合数字是不是很糟糕?
答案 0 :(得分:13)
如果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除外),你仍然可以获得均匀的哈希值分布。
答案 1 :(得分:2)
如果你知道哈希函数,那么你总是可以生成一组完美的输入数据,这将使哈希函数表现得很糟糕。没有“通用最佳”哈希函数。但总有一组最佳输入数据和一组最差的输入数据。
一个好的哈希函数应该将一个大集合X的任何子集映射到一个较小的输出集Y,在集合Y上具有最小和公平的冲突分布。
作为推论,没有任何方法可以预测哈希函数在没有任何数据集知识的情况下会很好,该函数将被认为是“好的”。
关于使用素数而不是复合数而不知道散列值的建议并不比声称87654321是散列的最佳模数更好。
如果要哈希素数或斐波纳契数,那么关于使用素数模数或复合模数或2的幂的建议是不相关的。
如果要对复合数字进行成对联合求值,则输入集合中每个元素的复合模数共同素数是“好”选择的候选者。比输入集的所有元素的最大因子大的主模数是另一个“好”选择。
如果您的输入集是一个区间内的稀疏整数集,并且数字之间的间隔是高斯分布,那么模数的“最佳”选择是一个最小化gcd出现的数字(模数,输入数据)!= 1.这更可能发生在选择素数作为模数时。
这是建议使用素数的原因。