使用乘法方法的散列函数有哪些缺点

时间:2014-08-09 10:51:44

标签: algorithm hash hashtable

实现哈希函数有两种基本方法,几乎​​在每本教科书和CS课程中都有引用:

  1. 分区方法我们只是k mod m基本上选择m为素数而不是太接近2的幂。
  2. 乘法方法其中我们将k乘以一些精心选择的无理数(Knuth建议使用基于黄金比率的数字)在0到1之间,取产品的小数部分并使用所需数量的最重要的一点。
  3. 大多数教科书和课程都列举了方法1的一些缺点,包括它昂贵且事情取决于m的事实。然而,我从未见过任何教科书或课程提到方法2的单一劣势。

    这使方法2更令人满意。此外,方法2可以在现代计算机上非常有效地消除浮点运算。因此看起来方法2看起来是赢家,并且没有人应该谈论方法1.但事实显然并非如此。事实上,我从未见过在任何实际实现中使用方法2。所以它确实有一些缺点。

    问题是它们是什么以及为什么方法1被更频繁地使用,尽管它有缺点?

1 个答案:

答案 0 :(得分:3)

分区方法与需要主表大小的哈希表算法结合使用 - 例如,使用双哈希或QHash的开放寻址,当你无论如何需要按表大小划分密钥或哈希时得到索引。

当表大小是2的幂时,乘法方法是合适的,然后从散列中获取索引可以实现为按位AND运算,因此通过密钥计算表索引的整个路径,使用乘法散列,是非常快。您可以通过searching for magic constant 2654435769 on Github探索一些实际的实现。

最近有使用MurmurHash3雪崩程序而非乘法方法的趋势:

int hash = key;
hash ^= (hash >> 16);
hash *= 0x85ebca6b;
hash ^= (hash >> 13);
hash *= 0xc2b2ae35;
hash ^= (hash >> 16);
// see this code and the version for 64 bits here:
// https://smhasher.googlecode.com/svn/trunk/MurmurHash3.cpp

因为它只是稍慢一点,但被认为对于错误的密钥分发更加健壮。这就是为什么你可能会错误地(或者说对了?)很少使用乘法方法的印象。