我正在使用此哈希函数,但遇到了很多冲突。目的是添加元素的ascii值并输出该值。有什么方法可以优化此功能或其他功能以减少碰撞次数?
int hash(char* s)
{
int hash = 0;
while(*s)
{
hash = hash + *s;
s++;
}
return hash;
}
答案 0 :(得分:3)
32位int
的范围超过40亿。 (如果您的int
是64位的,则范围会更大。)但是您的代码只是将字符串中每个字符的值相加,因此永远不会超出上限。您所有的哈希码都将是较小的数字,拥挤了可能的值的下限,并增加了发生冲突的机会。
这就是为什么好的算法会比这更复杂的原因。
Here's one article出现在Google的快速搜索中。
答案 1 :(得分:0)
“ foo bar”和“ bar foo”哈希值相同吗?实现这种方式的目的是使用ascii值及其在字符串中的位置来计算哈希,我天真地想象这将大大减少冲突。
int hash(char* s)
{
int hash = 0;
int pos = 0;
while(*s)
{
pos++;
hash += (*s * pos);
s++;
}
return hash;
}
尝试一下,看看是否有帮助。我对此答案没有太多的理论知识。
如下所述,使用EDIT *,您可能希望哈希为无符号整数。我在codechef.com上进行了测试,这是源代码和结果:
#include <stdio.h>
unsigned int hash(char* s);
unsigned int hash2(char* s);
int main(void) {
unsigned int temp1 = hash("foo bar");
unsigned int temp2 = hash("bar foo");
printf("temp1 is %d and temp2 is %d\n",temp1, temp2);
temp1 = hash2("foo bar");
temp2 = hash2("bar foo");
printf("temp1 is %d and temp2 is %d\n",temp1, temp2);
return 0;
}
unsigned int hash(char* s)
{
unsigned int hash = 0;
while(*s)
{
hash = hash + *s;
s++;
}
return hash;
}
unsigned int hash2(char* s)
{
unsigned int hash = 0;
int pos = 0;
while(*s)
{
pos++;
hash += (*s * pos);
s++;
}
return hash;
}
输出:
temp1为665,temp2为665
temp1为2655,temp2为2715
答案 2 :(得分:0)
是的,您的“哈希”函数将对包含相同字母的字符串(例如“铁路安全”和“童话”)产生冲突。 这是因为您仅使用可交换的加法。
您可以使用像素数这样的东西。
unsigned long int hashBetter(const char* s)
{
unsigned long int hash = 1234567890ul;
while(*s)
{
hash = (*s + hash) * 4294967291ul;
s++;
}
return hash;
}
或者您涉及一个CRC,它将输入数据广泛分布在可能的哈希值的有效范围内:
unsigned long int hashGood(const char* s)
{
unsigned long int hash = 1234567890ul;
while(*s)
{
hash = crc(hash, *s);
s++;
}
return hash;
}