计算散列大小的正确方法是什么 table

What is a propper way of calculating the size of a hash table

我正在构建哈希 [​​=13=] 使用双重哈希来解决冲突。我怎么知道合适的尺寸是多少?我知道它必须素数才能最大程度地减少碰撞次数。

不,将大小设置为素数没有意义,这会给您增加很多额外的工作。只需将大小设置为 2 的幂,并在哈希 table 中的对象数量达到某个阈值(例如大小的 50% 或 25%)时将其加倍。

如果您要询问当前大小,您可以使用 sizeof(table)/sizeof(element) 函数,因为您使用的是双重哈希方法。 如果您询问散列的新大小 table 一旦满(通过某个标准),那么最常见的是添加 10 个新槽。这应该基于您使用 table 的目的。大多数内置 tables 在其他语言中的默认设置是如果 0.75 满,则添加 10 个插槽。 如果是关于其他问题,请修改您的问题,使其更具描述性。 编辑:我刚刚注意到我上面的答案,我认为使用 2^p 方法在指数增长 tables 中也很常见,并且对双重哈希非常有帮助。

实现哈希 tables 的最简单方法是使用 power-of-2 大小的哈希 tables。

原因是如果N=2M,那么计算H % N就和计算H & (N - 1).

一样简单

对于 MurmurHash3_32 等快速散列函数,使用散列 table 最慢的部分实际上是计算模数。 H & (N - 1) 不计算模数,而是按位与,速度更快(如果 N 是 2 的幂,则与模数相同)。

有人可以有效地声称 MurmurHash 遭受 seed-independent 多重冲突,因此容易受到哈希冲突拒绝服务攻击。没错,但您不应该使用链表来解决散列冲突。你应该只使用散列 tables,其中键是 sortable 通过一些比较函数(大于,等于,小于)然后你可以使用 red-black 树(或 AVL 树)解决哈希冲突。如果没有自然的比较函数(例如复数),你可以发明一个。

使用几乎总是只有单个根元素的 red-black 树与 MurmurHash 比尝试通过使用 SipHash 来“安全”然后愚蠢地使用链表来解决哈希冲突(这导致首先需要慢得离谱的 SipHash)。

理论上,对于大小很少变化的非power-of-2 大小的散列 tables,您可以使用“使用乘法快速除以不变整数”技巧,但那是比 power-of-2-sizing 和按位与慢。

质数大小仅适用于非常差的哈希函数。 MurmurHash,虽然它遭受 seed-independent 多重冲突,但如果 table 大小是 2 的幂,则不会与合理的 (non-attacker-generated) 键发生冲突。