一个好的经验法则(并不总是理想的,嗯,只是一个经验法则)是在哈希表填充到 80% 时重新散列。这意味着如果你有 100 个桶和 80 件物品,无论你之前有多少碰撞,都需要时间来增加容量。
你应该增加多少?好吧,也没有完美的价值。最简单的解决方案是每增加一倍容量。所以它会达到 200、400、800 等等。如果您认为这太多了(毕竟当哈希表变得非常大并且您可能永远无法填满 16 MB 时,它会从 8 MB 内存跃升至 16 MB),请选择较小的增长因子。建议至少 1/3(从 100 增长到 133)我会说,作为妥协,也许让它每次增长 50%。
请注意,所有这些还取决于如何处理冲突。处理它们的一种简单方法(我个人最喜欢的)是在发生碰撞时将项目存储在链表中。如果将 3 个项目放在同一个键上,则仍然最多只有 3 次比较才能找到它。由于链表对搜索非常无效,您可能希望提前增加容量,例如,如果使用 60% 的容量来保持哈希表的快速。OTOH,您可以做一些更复杂的事情并保留有关碰撞次数的统计信息。只要你几乎没有任何冲突(如果你有一个非常好的散列函数),就根本不需要重新散列,即使它的 99% 的容量都在使用中。此外,如果您以复杂的方式处理碰撞(例如 每个节点又是一个排序表,您可以在这些表中执行二进制搜索)如果表加载到 200%,您的查找可能仍然足够快(因此您的项目数量是容量的两倍)。在这种情况下,您可以统计最大的排序表有多大,当它大于 8 个条目时,您认为这太慢了,然后您重新散列。
重新散列非常慢,因此应尽可能避免。因此,如果您需要重新散列,不要只是将容量增长得太少,否则在添加更多项目时您必须很快再次重新散列。所以当你需要重新散列时,让容量明显大于当前表中的项目数,其他的都是容量太少。