我一直在研究哈希表,其中一些数据被散列并用于存储桶索引。
有些库使用散列的模数和桶大小,其他库使用位掩码。 只使用桶掩码使用的位(确保不超出范围)。
的位掩码:
index = h->hash_func(key) & h->hash_mask;
模:
index = h->hash_func(key) % h->bucket_tot;
虽然两者之间存在明显的差异,例如使用位掩码的桶大小限制,但确保散列在较低位,模数速度等方面提供了良好的分布。
是否有充分的理由选择一个而不是另一个?
(我可能会尝试使用我自己的用例进行基准测试,但对这个问题已经很奇怪了。)
注意,这仅适用于键:值存储,(字典/散列/关联数组)和不安全相关。
使用位掩码动态调整大小,链接哈希表实现的示例:
使用modulo的示例:
答案 0 :(得分:2)
你提到了“桶”索引所以我假设你的意思是使用单独链接作为冲突解决方案的哈希表,在这种情况下,没有理由使用你提到的模数或位掩码“更强”(BTW不那么明显,如你说)。
在某些语言中,最值得注意的是基于Java / JVM,数组索引是带正号的32位整数,因此位掩码的最大数组大小为2 ^ 30,这可能是不够的,并且使用无功率的强大理由-of-two table size和modulo,使用它可以非常接近2 ^ 31-1(最大可能的带符号32位整数)。但是,既然您使用了C ++语法,那么这对您来说不应该是一个问题。
此外,如果您不仅意味着单独链接,则某些开放式寻址冲突解决算法要求表大小满足某些条件,例如,如果实现双重散列,则表大小应为素数。在这种情况下,你显然应该只使用modulo来获取表中的初始索引。
答案 1 :(得分:1)
它也不仅仅与性能有关,有时它与您的问题领域有关。例如,您可能有一个希望对负数进行哈希处理的掩码。使用模数,你必须编写特殊情况来处理它们,而不是使用位掩码。