【发布时间】:2021-01-07 14:11:33
【问题描述】:
我正在关注一篇文章,其中我有一个包含固定数量 2048 个篮子的哈希表。
哈希函数采用指针和哈希表本身,将地址视为位模式,将其右移三位并以哈希表的大小为模(2048)减少它:
(这里写成宏):
#define hash(p, t) (((unsigned long)(p) >> 3) & \
(sizeof(t) / sizeof((t)[0]) - 1))
然而,这篇文章并没有详细说明为什么它将地址右移三位(起初似乎有点武断)。我的第一个猜测是,原因是通过切断最后三位来对具有相似地址的组指针进行排序,但鉴于分配给一个应用程序的大多数地址无论如何都有相似的地址,我不明白这会有什么用;以此为例:
#include <stdio.h>
int main()
{
int i1 = 0, i2 = 0, i3 = 0;
printf("%p\n", &i1);
printf("%p\n", &i2);
printf("%p\n", &i3);
printf("%lu\n", ((unsigned long)(&i1) >> 3) & 2047); // Provided that the size of the hash table is 2048.
printf("%lu\n", ((unsigned long)(&i2) >> 3) & 2047);
printf("%lu", ((unsigned long)(&i3) >> 3) & 2047);
return 0;
}
另外,我想知道为什么它选择 2048 作为固定大小,这是否与三位移位有关。
作为参考,本文摘自 David P. Hanson 的“C 接口和实现,创建可重用软件的技术”。
【问题讨论】:
-
也许让固定大小的哈希表更小? (反题回答)。
-
但是为什么要将它右移 3 位呢?
-
因为你想在内存消耗(尽可能小)和性能(尽可能少的冲突)之间保持良好的“平衡”......设计哈希时总是如此-table 解决方案。
-
哦,等等,不是这样...假设
sizeof(long) == 8,在大多数架构上,前 3 位为零。因此,您希望“摆脱它们”以减少哈希表中的冲突次数。 -
每隔一个哈希值就会重复一次