最好是快速方式。 N = 2^b
案例非常简单。对于它,首先我要弄清楚我选择的类型中有多少位:
typedef unsigned int type;
size_t size = sizeof(type) * 8;
然后我将通过适当的位数执行右移以产生高b
位的散列键。
type input = 0x657;
unsigned char b = 4;
unsigned char hash = input >> (size - b);
但如果我想要N = 3
怎么办?或者2的任何其他非权力?假设我的N
总是适合unsigned char
(所以最多只有256个),那么散列一些input
的最快方法是什么?虽然保持桶的范围不超过+/- 1,但也保留input
的高位的顺序,就像上面的函数一样。
答案 0 :(得分:3)
对于32位值,使用N
进行64位乘法并保持前32位。 (类似地,对于其他大小,尽管如果你有64位值,乘法变得更加棘手。)
这是一个基本的证明大纲。
很明显,这种映射是保持秩序的;唯一的问题是每个桶中有多少值。现在,考虑一些存储桶j
并找到映射到该存储桶的最小i
。如果i
落入存储区j
,则表示Ni − j×232 = m
位于0 ≤ m < 232
,但如果i
是最小的此类值0 ≤ m < N
。 (否则,i−1
也会落入专栏j
。)
现在,定义w = ⌊232∕N⌋
,这相当于说Nw − 232 = −m' where 0 ≤ m' < N
。通过添加这两个公式,我们发现Ni + Nw - j×232 - 232 = m−m'
;简化,我们得到N(i+w)-(j+1)×232 = m−m'
和−N < m−m' < N
。这意味着i + w
或i + w + 1
是映射到j + 1
的最小值(取决于m − m'
是否为负数),这意味着有w
映射到w + 1
的1}}或j
值。由于任何j
都是如此,我们可以肯定地说只有两个存储桶大小,其中一个是⌊232∕N⌋
。我在评论(现已删除)中做出的断言与其他可能的桶大小为⌈232∕N⌉
的距离不远。
上述证据中232
没有任何魔力;我可以使用任何值M
。但这会使浓缩证据难以阅读。