哈希表:为什么大小应该为素数? [重复]

问题描述 投票:25回答:2

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

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

据我了解,它可以确保分配更均匀,但是还有其他原因吗?

data-structures
2个回答
32
投票

唯一的原因是避免将值聚类到少量的存储桶中(是,分布)。分布更均匀的哈希表将更一致地执行。

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

如果假设您的hashCode函数在以下{x,2x,3x,4x,5x,6x ...}中导致以下hashCode,那么所有这些将被聚类在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,即通过使table_length与x互质来使m等于table_length。如果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


-5
投票

无论使用哪种哈希函数,您都会得到一个整数。为了将其映射到哈希表,通常需要mod具有哈希表大小的整数,以使该值小于表的大小以进行映射。

返回hashVal%tableSize

从那时起我有点迷茫,但是IIRC如果tableSize是偶数,则所有条目都将是偶数。您的哈希表的一半将永远不会填充。

© www.soinside.com 2019 - 2024. All rights reserved.