C++ 什么';英语单词的哈希函数是什么?

C++ 什么';英语单词的哈希函数是什么?,c++,c,hash,C++,C,Hash,我有一长串英语单词,我想把它们散列出来。什么是好的散列函数?到目前为止,我的哈希函数对字母的ASCII值求和,然后对表大小进行模化。我正在寻找一种高效、简单的方法。也许这样的方法可以帮助您: 它为输入域生成一个优化的哈希函数。简单地对字母求和不是一个好的策略,因为排列会给出相同的结果 这个()非常流行,可以很好地处理ASCII字符串 unsigned long hashstring(unsigned char *str) { unsigned long hash = 5381;

我有一长串英语单词,我想把它们散列出来。什么是好的散列函数?到目前为止,我的哈希函数对字母的ASCII值求和,然后对表大小进行模化。我正在寻找一种高效、简单的方法。

也许这样的方法可以帮助您:


它为输入域生成一个优化的哈希函数。

简单地对字母求和不是一个好的策略,因为排列会给出相同的结果

这个()非常流行,可以很好地处理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;
}
无符号长哈希字符串(无符号字符*str)
{
无符号长散列=5381;
INTC;
而(c=*str++)

hash=((hash如果您不需要加密安全,我建议使用杂音hash。它速度非常快,扩散性很强。易于使用

如果您确实需要一个加密安全的散列,那么我建议通过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
}
散列数也非常均匀地分布在可能的范围内,没有我可以检测到的聚集-这只是使用随机字符串检查的。
[编辑]
还针对从本地文本文件中提取的单词以及LibreOffice字典/同义词库单词(英语和法语-超过97000个单词和结构)进行了测试,其中64位为0冲突,32位为1冲突:)


(与同一组上的FNV1A_Hash_Yorikke、djb2和MurruHash2相比:Yorikke和djb2表现不好;slash_Hash在所有测试中都略好于MurruHash2)

不,它只是一个“种子”,相当随意。@MikeG:这是“种子”或起始值。这一个通常被称为“乘以33”哈希。@sixlettervariables我在哪里指定表长度?如果它返回的数字大于我的表怎么办?理论上,它可以返回任何有效的
无符号long
值。根据您的约束,由您来操作哈希。@MikeG:通常,您不会在哈希算法中指定表大小(如果您不知道,请使用一个已经制作好的表…)。该表可能会根据项目的数量增长或收缩(对于良好的实现),所以你只需计算散列,然后取散列模当前大小,就可以知道将其放入哪个存储桶中。+1对于MurrushHash,你知道CityHash和MurrushHash之间是否存在比较吗?我听说了两者的优点,但从未看到过全面的比较,只是有一些轶事。在这里检查可能的重复和一个good这个问题的答案可以在其他stackexchange站点上找到:这是一个合理的哈希函数。我建议避免使用未命名的联合。-->
union{uint64_t h;uint8_t u[8];}uu;
以及类似的代码更改-->
uu.h=strlen;
..
uu.u[I%8]+==…
等等