c - 我应该使用什么哈希从一组字符串中生成随机值

标签 c arrays random hash buckets

我在哈希桶中有一组指纹。我想插入存储桶并搜索它,而不是从条目 0 到条目 n。

我想做的是,当我将条目添加到存储桶中时,我使用指纹作为输入来计算哈希值,我可以使用该哈希值来确定要添加到哪个存储桶中。这并不困难,但是当我尝试使用相同的算法对指纹进行哈希处理以识别将指纹添加到存储桶中的哪个插槽时,我发现它会产生很多冲突。

这是我用来将指纹散列到存储桶中的代码。我尝试使用具有更多字符的相同代码,但它仍然给我带来更高的碰撞。

he.fingerprint is 33 characters wide

number of buckets is 1024

number of entries per bucket is 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;

最佳答案

您的哈希函数中有一些多余的东西。

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];

因此任何索引处的小差异(最后一个索引除外,但您也可以再次乘以传播它们)会产生哈希值的大差异。

关于c - 我应该使用什么哈希从一组字符串中生成随机值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9606011/

相关文章:

计算数组中有多少个字段已满

c - 为什么会损坏声音?

c - 如何确定确切原因,为什么 berkeley db 在 db->open 上返回 EINVAL?

javascript - 如何在执行map()循环后调用函数

php - 如何使用 jQuery AJAX 和 PHP 数组返回

c++ - Windows 和 Linux 中的毫秒级随机种子

javascript - 从不规则范围中获取随机数

c - 在 C 中从 typedef 结构设置和获取数组的值

php - 如何通过 URL 参数将 Javascript/jQuery 数组发送到 PHP?

javascript - 如果他们得到某个字符串,我该如何重定向用户