直接根据高位将整数散列到N个大小大致相等的桶中(维持顺序)
Hash integers into N roughly equal sized buckets directly based on upper bits (maintaining order)
最好是一种快速的方法。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
的最快方法是什么?同时保持bucket的范围差不超过+/-1,并保持input
的高位的顺序,就像上面的函数一样。
对于32位值,用N
进行64位乘法运算,并保留前32位。(类似地,对于其他大小,尽管如果您有64位值,乘法会变得更困难。)
这是一个基本的证明大纲。
很明显,这种映射是保序的;唯一的问题是每个桶中有多少个值。现在,考虑一些bucketj
,并找到映射到该bucket的最小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'
是否为负),这意味着存在映射到j
的w
或w + 1
值。由于任何j
都是如此,因此我们可以肯定地说,只有两种bucket大小,其中一种是⌊232∕N⌋
。离我在评论(现已删除)中所做的断言不远了,即另一个可能的bucket大小是⌈232∕N⌉
。
在上述证明中,232
没有什么神奇之处;我可以使用任何值M
。但这会使浓缩的校样更难阅读。
- 比较并显示使用最小值(a,b)和最大值(a、b)升序排列的4个数字
- 为什么在浮点中从大到小会引入更多的误差
- 最大和最小 1 C++函数
- 如何创建一个函数来计算并返回平均值、最大值和最小值
- 在二维数组中查找最小值和最大值?
- 查找矩阵C++中每一列和每一行的最小和最大元素
- 有没有办法在 c++ 中按更大的 int 和更小的对对 int 和对的集合进行排序?
- 如何在数组中交换最小和最大的位置?
- 查找数组中第一个最小值和最后一个最大值元素之间的算术平均值
- 从较小的阵列到较大的阵列的元素级转换
- C++ 函数,用于查找传入的 N 个数字的平均值、总和、最小值和最大值
- txt 文件中浮点数的最大和最小值
- 查找最小的下一个更大的元素
- 在最小堆中查找最大元素
- C++不同的最小最大值实现
- 将网络字节顺序(大字节序)转换为小字节序
- 数组内存地址总是按最小到最大的顺序排列吗
- 在 c++ 中给出两个整数向量(大小和类型相同),我想从最小到最大元素对一个进行排序,并更改第二个向量的顺序
- 按顺序读取大文件
- 使用Std::vector::reserve时,Std::sort顺序从大到小