C - 为 int 三元组制作哈希函数

Posted

技术标签:

【中文标题】C - 为 int 三元组制作哈希函数【英文标题】:C - making hash function for int triples 【发布时间】:2015-06-12 17:30:15 【问题描述】:

我需要为这种三元组实现某种集合数据结构: (int, int, int),其中前 2 个 int 来自未知范围,而第三个 int 通常很小。我不需要任何关于订购的信息,所以我决定使用 HashSet。我从来没有实现过类似的东西,但我读过它真的很容易搞砸并且在使用时性能很差。

这是我打算做的。我制作了一大堆可调整大小的桶,并且(散列函数 % 大小)给出了将三元组放入的桶的数量。我知道我需要均匀地使用所有桶以使其高效。问题是:这样做的正确方法是什么? “(a+b+c) mod size”是否足够高效或者我需要使用更复杂的东西?

【问题讨论】:

a + b + c 显然是一个非常糟糕的选择,因为值的任何排列都将具有相同的哈希值。通常,您希望尽可能多地混合所有成分。对一般散列函数进行一些研究,然后将敏感算法应用于所有组成位。 见:***.com/a/1362712/2697007 请注意,您仍然必须为具有相同哈希的不同值做出规定。 【参考方案1】:

不要使用琐碎的散列函数,因为分散远非最优,并且发生冲突的概率很高。哈希函数已成为许多研究的对象,您应该首先从 wikipedia page 开始 - 对于您的使用,您应该考虑非加密函数。

如果不确定,FNV-1a 哈希通常被认为是正确的(摘自***):

hash = FNV_offset_basis
for each byte_of_data to be hashed
     hash = hash XOR byte_of_data
     hash = hash × FNV_prime
return hash

如果你想要 32 位哈希,质数是 224 + 28 + 0x93 = 16777619

好在产品可以写成少量的移位和加法:

hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);

参考:FNV Hash

【讨论】:

"乘积可以写成移位和加法的好处是" 任何乘法都不是这样;-)?但是,如果桶的数量是 2 的幂,则可以对其进行优化。 @Olaf 我应该说少量轮班... - 已编辑 对于带有乘法器的 CPU,它很可能会使事情变得更糟,对于小型 MCU,它可能会有所帮助。但这些很少需要 32 位哈希。不过,我很欣赏你的想法。 @Olaf 在我参考的页面上,您可以找到一些不同大小的哈希的实现。而优化是可选的... 我非常了解 FNV 哈希。在changed to SipHash 之前,它在修改版本中用于 Python 很长时间。我个人喜欢它的简单性和速度。如果您不必担心攻击,我认为它是许多应用程序的绝佳选择。

以上是关于C - 为 int 三元组制作哈希函数的主要内容,如果未能解决你的问题,请参考以下文章

C函数学习:uthash哈希表

C函数学习:uthash哈希表

C函数学习:uthash哈希表

C函数学习:uthash哈希表

如何使用 c++ 将字符串散列为 int?

C++ std::unordered_map 中使用的默认哈希函数是啥?