【问题标题】:How does perl resolve possible hash collisions in hashes?perl 如何解决哈希中可能的哈希冲突?
【发布时间】:2018-06-13 11:54:16
【问题描述】:

众所周知,perl 将其“哈希”类型实现为具有计算索引的表,其中这些索引是截断的哈希。

我们也知道,散列函数可以(并且将根据概率)碰撞,将相同的散列提供给 2 个或更多不同的输入。

那么:当 perl 解释器发现一个键生成的哈希值与另一个键相同时,它会如何处理?它能处理它吗?

注意:这不是关于哈希算法,而是关于哈希表实现中的冲突解决。

【问题讨论】:

标签: perl hashmap


【解决方案1】:

Perl 哈希是一个链表数组。

+--------+       +--------+
|       -------->|        |
+--------+       +--------+
|        |       | key1   |
+--------+       +--------+
|      ------+   | val1   |
+--------+   |   +--------+
|        |   |
+--------+   |   +--------+     +--------+
             +-->|       ------>|        |
                 +--------+     +--------+
                 | key2   |     | key3   |
                 +--------+     +--------+
                 | val2   |     | val3   |
                 +--------+     +--------+

散列函数产生一个值作为数组索引,然后对关联的链表进行线性搜索。

这意味着查找的最坏情况是 O(N)。那么为什么人们说它是 O(1) 呢?你可以声称如果你让列表不超过某个恒定长度,这就是 Perl 所做的。它使用两种机制来实现这一点:

  • 增加存储桶的数量。
  • 哈希算法受到干扰。

平均而言,将桶数加倍应该将给定的条目数除以一半。例如,

305419896 % 4 = 0 and 943086900 % 4 = 0
305419896 % 8 = 0 and 943086900 % 8 = 4

但是,恶意行为者可以选择不会发生这种情况的值。这就是哈希扰动发挥作用的地方。每个散列都有自己的随机数,它会扰乱(导致变化)散列算法的输出。由于攻击者无法预测随机数,因此他们无法选择会导致冲突的值。需要时,Perl 可以使用新的随机数重建哈希,使键映射到与以前不同的存储桶,从而分解长链。

【讨论】:

  • 这是一个单独的链表链接。这引发了另外两个问题:随机是盐吗?我得到 perl 从一个小表开始,然后增长它,所以我猜它掩盖了散列,然后冲突会更多。它是通过占用的存储桶数还是通过方便来增加表的?也许这值得另一个问题,以及一个概率研究来理解这个选择。
  • 你可以称之为盐,是的。 /// 桶数翻倍
  • 我知道它是数字的两倍(它停止屏蔽一点)。但是它什么时候说:“好吧,让我们把桌子扩大”?它只是计算占用的桶数(相对于分配的)还是其他类型的东西?
  • 当然可以,但当链条过长时也是如此。
  • 我认为 perl repo 中的这个提交就足够了:commit。谢谢。
【解决方案2】:

键产生相同哈希值的键值对集合一起存储在链表中。血腥细节可在hv.c 中找到。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-30
    • 1970-01-01
    • 2018-11-05
    • 2016-07-30
    相关资源
    最近更新 更多