【问题标题】:Hash table: why size should be prime? [duplicate]哈希表:为什么大小应该是素数? [复制]
【发布时间】:2011-04-28 03:56:45
【问题描述】:

可能重复:
Why should hash functions use a prime number modulus?

为什么哈希表(数据结构)的大小必须是素数?

据我了解,它保证了更均匀的分布,但还有其他原因吗?

【问题讨论】:

  • 这是Why should hash functions use a prime number modulus? 的副本——侧边栏“相关”部分的第一个链接——我认为accepted answer 非常好。
  • 你应该接受答案。
  • 我刚刚注意到这被标记为重复。那真不幸。这是两个相关但独立的问题。这个特定的问题是关于在哈希表容量中使用素数的。另一个是关于在计算适当的值时使用素数。它们相互关联,但不重复。

标签: data-structures


【解决方案1】:

唯一的原因是避免将值聚集到少数桶中(是的,分布)。分布更均匀的哈希表会表现得更一致。

来自http://srinvis.blogspot.com/2006/07/hash-table-lengths-and-prime-numbers.html

如果假设您的 hashCode 函数产生以下 hashCodes 以及其他 {x , 2x, 3x, 4x, 5x, 6x...},那么所有这些都将聚集在 m 个桶中,其中 m = table_length/GreatestCommonFactor(table_length, x)。 (验证/推导这一点很简单)。现在您可以执行以下操作之一来避免聚集

  1. 确保您不会生成太多的 hashCode,这些 hashCode 是另一个 hashCode 的倍数,例如 {x, 2x, 3x, 4x, 5x, 6x...}。但是如果您的 hashTable 是应该有数百万个条目。

  2. 或者简单地通过使 GreatestCommonFactor(table_length, x) 等于 1 使 m 等于 table_length,即通过使 table_length 与 x 互质。如果 x 可以是任何数字,那么请确保 table_length 是一个素数。

更新:(来自原始答案作者)

这个答案对于哈希表的常见实现是正确的,包括原始 Hashtable 的 Java 实现以及 .NET 的 Dictionary 的当前实现。

不过,对于 Java 的HashMap,容量应该是素数的答案和假设都不准确。 HashMap 的实现非常不同,它使用大小为 2 的表来存储桶,并使用 n-1 & hash 来计算要使用的桶,而不是更传统的 hash % n 公式。

Java 的 HashMap 将强制实际使用的容量为请求容量之上的下一个最大的以 2 为底的数字。

比较Hashtable:

int index = (hash & 0x7FFFFFFF) % tab.length

https://github.com/openjdk/jdk/blob/jdk8-b120/jdk/src/share/classes/java/util/Hashtable.java#L364

HashMap

first = tab[(n - 1) & hash]

https://github.com/openjdk/jdk/blob/jdk8-b120/jdk/src/share/classes/java/util/HashMap.java#L569

【讨论】:

  • 我猜我的理解是对的:避免集群 获得更好的分布。正确的?感谢您的参考。
  • @Olivier Lalonde,如果这回答了您的问题,请将其标记为答案。
  • then all these are going to be clustered in just m number of buckets, where m = table_length/GreatestCommonFactor(table_length, x). (It is trivial to verify/derive this) 如何验证/推导出这个?
  • @tonix 这是一个引用,但我假设您可以通过创建一个表示桶的整数数组来模拟将大量项目添加到哈希表,循环大量项目,将每个项目添加到适当的数组元素。如上所述,一个分布良好的哈希表在每个数组元素中都有相似的数字。分布不佳的索引(例如在第一个示例中使用非素数)会在某些索引中显示峰值。
  • @SamuelNeff 感谢您的回复 Samuel,但我正在寻找一种方法来证明这一点。
猜你喜欢
  • 2011-08-21
  • 2014-05-17
  • 1970-01-01
  • 2018-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-07
  • 1970-01-01
相关资源
最近更新 更多