Data structures 哈希表:为什么大小应该是素数?

Data structures 哈希表:为什么大小应该是素数?,data-structures,Data Structures,可能重复: 为什么哈希表(数据结构)的大小必须是素数 据我所知,它确保了更均匀的分布,但还有其他原因吗?唯一的原因是避免将值聚集到少量存储桶中(是的,分布)。更均匀分布的哈希表将执行更一致的操作 从 如果假设您的hashCode函数产生以下hashCode以及其他{x,2x,3x,4x,5x,6x…},那么所有这些都将聚集在m个bucket中,其中m=table_length/GreatestCommonFactor(table_length,x)。(验证/推导这一点很简单)。现在,您可以执行

可能重复:

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


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

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

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

  • 请确保您不会生成太多的哈希代码,这些哈希代码是{x,2x,3x,4x,5x,6x…}中另一个哈希代码的倍数。但是如果您的哈希表应该有数百万个条目,那么这可能有点困难

  • 或者简单地通过使最大公因子(table_length,x)等于1,即通过使table_length与x互质,使m等于table_length。如果x可以是任意一个数,那么确保table_length是一个素数

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

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

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

    Java的
    HashMap
    将强制实际使用的容量为请求容量之上的第二大基数2

    比较哈希表:

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

    HashMap

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

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

    返回hashVal%tableSize


    从这一点开始我有点不知所措,但是IIRC如果tableSize是偶数,那么所有条目都是偶数。哈希表的一半永远不会被填充。

    我想我的理解是正确的:避免集群,获得更好的分布。对吗?谢谢你的推荐。@Olivier Lalonde,如果这回答了你的问题,请将其标记为答案。这是另一个很好的观点。我相信素数的原因是它降低了hashVal中模式的风险(例如10,20,30,40,如果tableSize=10,所有模式都将为0),这可能会导致@Sam.347%20是7,这是不均匀的。这是“相关”中的第一个链接的重复侧边栏的一部分-我认为这是非常好的。你应该接受一个答案。我刚刚注意到这被标记为一个副本。那太不幸了。这是两个相关但独立的问题。这个特殊的问题是关于素数在哈希表容量中的用法。另一个是关于素数在计算适当的has值时的用法。它们相互关联,但不是重复的。