我正在使用这个散列函数,但是我得到了很多冲突。其目的是将元素的ascii值相加并输出值。有没有办法优化这个函数或其他函数,以减少冲突的数量?
int hash(char* s)
{
int hash = 0;
while(*s)
{
hash = hash + *s;
s++;
}
return hash;
}发布于 2018-10-12 05:24:33
32位int的范围超过40亿。(如果您的int是64位的,则范围要大得多。)但是您的代码只是简单地将字符串中每个字符的值相加,它永远不会接近上限范围。所有的哈希码都将是较小的数字,挤占了可能值的低端,并增加了冲突的机会。
这就是为什么一个好的算法会比这个更复杂。
在谷歌快速搜索中出现的Here's one article。
发布于 2018-10-12 05:58:51
"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*如下所述,您可能希望hash是一个无符号整数。我在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
发布于 2018-10-12 07:09:40
是的,您的"hash“函数将对由相同字母组成的字符串产生冲突,例如"rail”和“rail”。这是因为你只使用了可交换的加法。
你可以使用像这样的东西,它包含一个素数作为因子。
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;
}https://stackoverflow.com/questions/52769024
复制相似问题