我有一长串英文单词需要进行哈希处理。你能给出一个好的哈希函数吗?目前我的哈希函数是将字母的ASCII值相加,再取模表格大小。我正在寻找一些高效简洁的方案。
我有一长串英文单词需要进行哈希处理。你能给出一个好的哈希函数吗?目前我的哈希函数是将字母的ASCII值相加,再取模表格大小。我正在寻找一些高效简洁的方案。
简单地对字母求和并不是一个好策略,因为不同排列的结果相同。
这个(djb2)非常流行,并且对ASCII字符串效果很好。
unsigned long hashstring(unsigned char *str)
{
unsigned long hash = 5381;
int c;
while (c = *str++)
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
return hash;
}
更多信息请点击此处。
如果需要更多选择和一些性能指标,请在此处阅读。
添加:这些是通用的哈希函数,输入域事先未知(除非有一些非常一般的假设:例如上述对ascii输入略微更有效),这是最常见的情况。 如果您具有已知的受限域(固定输入集),则可以做得更好,请参见Fionn的答案。
http://en.wikipedia.org/wiki/MurmurHash
如果您确实需要一个加密安全哈希,我建议使用OpenSSL中的SHA1。虽然有点晚,但以下是一种哈希函数,其64位版本具有极低的冲突率,而32位版本则几乎一样好:
uint64_t slash_hash(const char *s)
//uint32_t slash_hash(const char *s)
{
union { uint64_t h; uint8_t u[8]; } uu;
int i=0; uu.h=strlen(s);
while (*s) { uu.u[i%8] += *s + i + (*s >> ((uu.h/(i+1)) % 5)); s++; i++; }
return uu.h; //64-bit
//return (uu.h+(uu.h>>32)); //32-bit
}
(还将其与相同数据集上的FNV1A_Hash_Yorikke、djb2和MurmurHash2进行比较:Yorikke和djb2表现不佳;斜杠哈希在所有测试中略优于MurmurHash2)
union { uint64_t h; uint8_t u[8]; } uu;
以及代码中类似的更改 -->> uu.h=strlen(s);
... uu.u[i%8] += ...
等。 - joop