我已经被分配为大学项目的任务,该任务是从头开始创建数据结构(例如minheap,hashtable等)。但是Hashtable或更具体地说是Hash映射-函数给我带来了很多麻烦。我遇到过MAD(乘,加,除)函数,基本上是:h(x)= [(a * x + b)%p]%N,其中a,b:随机整数,p:大质数N:哈希表中元素的数量。
我的问题是此函数如何(以及为什么)准确地将哈希表中的值均匀分布。
答案 0 :(得分:1)
h(x) = [(a*x + b) % p] % N
让我们首先单独查看a*x + b
。如果您想象a
分解为2的幂,则a*x
是x
的总和向左偏移2的次幂,使得{ {1}}影响在x
中设置的其他位的位置,当求和产生的其他一些位则携带特定的位。加a
会混入另一组随机位:非常类似于XORing,但进位会有一些额外的复杂性。如果说b
的值介于0到255之间,并且具有x
位(每个都是0或1),那么到目前为止,我们已经得到:
abcdefgh
因此,在“ 1s”列中,我们对 (a&1 ? abcdefgh : 0) +
(a&2 ? abcdefgh0 : 0) +
(a&4 ? abcdefgh00 : 0) +
(a&8 ? abcdefgh000 : 0) +
... + // continues for a&16, a&32 etc.
ABCDEFGHIJKLMNOP // however many random bits in "b"
和h
求和,它们可能与P
,g
和{ {1}},然后继续。
如果h
等于37,即32 + 4 + 1,则我们要添加O
本身,a
和x
:{ {1}}因此会影响散列值中的更多位(这很好,的确具有密码强度散列函数,更改密钥中的任何位(无论是单个位,一半位还是全部位)都应该随机地翻转哈希值的一半)。
回到完整的公式,让我们假设我们跳过x << 2
而只有x << 5
,但是当前表的大小是2的幂:x
相当于按位-AND运算一些不那么重要的位。换句话说,它丢弃了我们在% p
计算的更高有效位中建立的许多随机性。因此,为了使散列函数可以安全地在任意数量的存储桶中使用,我们可以首先引入% N
,这意味着从求和步骤开始,如果散列值中存在与二幂幂相关的模式,则它们有效地分散在0..p范围内的随机位置上。
请考虑说一个介于0到255之间的哈希-如果% N
为200,则哈希到桶中0..55范围的可能性是原来的两倍。为了使这种影响不那么重要,我们希望散列值比MOD值具有更多的位,并且该原理以分层的方式应用于我们应为a * x + b
和% p
选择的值:< / p>
N
的值应倾向于明显大于p
,并且分布在比N
大得多的范围内,因此a * x + b
将它们在桶,但是
p
应该比p
大得多,因此我们没有低索引的存储桶,其碰撞概率明显更高(如果您使用线性探测来解决冲突)。
例如,如果我们要支持% p
的值,最大为2 24 ,并且我们使用32位无符号整数进行这些计算,那么p
和{ {1}}在该范围内具有随机值,我们可以将差值拆分为大约2 28 的质数。