C++ 直接基于高位将整数散列到N个大小大致相等的存储桶中(维持顺序)

C++ 直接基于高位将整数散列到N个大小大致相等的存储桶中(维持顺序),c++,algorithm,data-structures,C++,Algorithm,Data Structures,最好是一个快速的方法。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

最好是一个快速的方法。
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
总是放在
无符号字符
中(因此最多是256个),对一些
输入进行散列的最快方法是什么?在保持存储桶的范围差不超过+/-1的同时,也保持
输入的高位顺序,就像上面的函数一样。

对于32位值,使用
N
进行64位乘法,并保留前32位。(类似地,对于其他大小,尽管如果有64位的值,乘法会变得更复杂。)

这里有一个基本的证明大纲

很明显,这种映射是保序的;唯一的问题是每个桶中有多少个值。现在,考虑一些桶<代码> j>代码>,找到映射到那个桶的最小<代码> i>代码>。对于
i
落入桶
j
意味着
Ni− j×232=m
其中
0≤ m<232
,但如果
i
是这样的最小值,
0≤ m
。(否则,
i−1
也会落入桶
j

现在,定义
w=⌊232∕N⌋
,相当于说
Nw− 232&等于;−m'where 0≤ m'
。将这两个公式相加,我们发现
Ni+Nw-j×232-232=m−m’
;简化得到
N(i+w)-(j+1)×232=m−m'
−N
。这意味着
i+w
i+w+1
是映射到
j+1
的最小值(取决于
m− m'
是否为负值),这意味着存在映射到
j
w
w+1
值。因为这对任何
j
都是正确的,所以我们可以肯定地说只有两种桶大小,其中一种是
⌊232∕N⌋。这离我在评论(现在已删除)中的断言不远了,即另一个可能的bucket大小是
⌈232∕N⌉


在上面的证明中,
232
没有什么神奇之处;我可以使用任何值
M
。但这会使压缩证明更难阅读。

除以
N
是行不通的,这就像在
N=2^b
的情况下向右移位
b
位一样。使用除法我没有太大问题,但是如何除法并使桶尽可能接近相等的大小呢?哎呀,这就是我在匆忙中打字的结果。它应该除以MAXINT/N,这将简化为另一个表达式。@user173342完全重写了答案,使您的初始注释难以理解。抱歉。这个方法不能导致最后一个bucket比其余的bucket大N吗?@user173342,我认为这个方法实际上将舍入误差降到了最低。@Joe
N=256
bucket可以通过
无符号字符(0到255)来索引。将bucket的大小保持在+/-1是什么意思?您是否假设将每个整数分配到一个存储桶中?@templatetypedef我应该说每个存储桶的范围。