我在散列桶中有一系列指纹。我想插入到存储桶中并从条目0到条目n进行搜索。
我想要做的是,当我向桶中添加条目时,我使用指纹作为输入来计算哈希,我可以使用该哈希来确定要添加到哪个桶中。这并不困难,但是当我尝试使用相同的算法对指纹进行散列以识别存储桶中的哪个插槽来添加指纹时,我发现它会产生大量的冲突。
这是我用来将指纹散列到存储桶中的代码。我尝试使用相同的代码与更多的字符,但它仍然给我更高的碰撞。
he.fingerprint是33个字符宽
桶的数量是1024
每个桶的条目数是2048
char hph[32];
int bk,en;
unsigned long h = 0, g,i=0;
int j=0;
strncpy(hph,(const char*)(he).fing_print,32);
while ( j<32 )
{
h =h + hph[j]++;
g = h & 0xFFf00000;
h ^= g >> 24;
h &= ~g;
j++;
}
bk=h%buckets;
en=h%entries_per_bk;
答案 0 :(得分:3)
你的散列函数中有一些多余的东西。
char hph[32];
int bk,en;
unsigned long h = 0, g,i=0;
int j=0;
strncpy(hph,(const char*)(he).fing_print,32);
while ( j<32 )
{
h = h + hph[j]++;
实际上,这是h += hph[j];
。索引j
处的字符会递增,但由于它从未再次使用过,因此根本不会影响散列。也许你的意思是预先增量?但这不会有太大变化。
g = h & 0xFFf00000;
指纹(或至少你使用的部分)最多为32个字符。这些字符中的每一个都小于256,因此总和小于32*256 = 8192 = 0x2000
,因此h & 0xFFF00000
为0.因此,以下两行与h
完全无关。
h ^= g >> 24;
h &= ~g;
j++;
}
bk=h%buckets;
en=h%entries_per_bk;
如此有效,您的哈希值是指纹前32个字符的总和。这并没有很好地传播你的哈希,类似的字符串会产生类似的哈希值。你可以通过将哈希乘以一个较大的素数来获得更好的哈希值,
h = 0;
for(j = 0; j < 32; ++j)
h = prime*h + hph[j];
所以任何索引的小差异(除了最后一个,但你可以再次繁殖以传播它们)可以创建散列的大差异。