【问题标题】:best way to resolve collisions in hashing strings解决散列字符串冲突的最佳方法
【发布时间】:2012-02-09 08:18:16
【问题描述】:

我在一次面试中被问到这个问题,并说要使用第二个功能,但面试官一直在寻找其他答案。谁有其他解决方案?

【问题讨论】:

  • 链式每个节点花费一个指针并解决您的所有问题,但代价是失去引用的局部性。 (也将被二次散列丢失)
  • 散列用于什么目的?密码? MD5文件哈希?字典/哈希集?
  • @Darjan 用于字典
  • 固定字典(无插入/删除)?

标签: hash


【解决方案1】:

解决散列字符串冲突的最佳方法 “连续插入”

假设插入的是内容无法预测的字符串,那么合理的选择是:

  1. 使用位移列表,因此您可以尝试从 散列到桶,直到找到一个空闲桶(按表修改 尺寸)。置换列表可能类似于 { 3, 5, 11, 19... } 等-理想情况下,您希望在 位移不是一系列其他位移的总和。
  2. 使用不同的算法重新散列(但是你需要另一个 算法,如果你碰巧发生两次冲突等)
  3. 在 桶,以便可以搜索冲突的字符串。通常 存储桶的数量应等于或大于 元素的数量,因此每个桶的元素将相当小,并且 通过数组/向量进行蛮力搜索是合理的 方法,但链表也是可信的。

比较这些,置换列表往往是最快的(因为添加偏移量比计算另一个散列或支持单独的堆和分配更便宜,并且在大多数情况下,前一个或两个置换(可以合理地由少量buckets) 足以找到一个空的桶,因此内存使用的局部性是合理的)尽管它们比替代散列算法更容易发生冲突(应该接近 #elements/#buckets 进一步冲突的机会)。对于置换列表和重新散列,您必须提供足够的重试次数,以便在实践中您不会期望完全失败,添加一些对失败的最后手段处理,或者接受可能发生的失败。

【讨论】:

    【解决方案2】:

    使用链表作为哈希桶。因此,任何碰撞都会得到妥善处理。

    【讨论】:

      【解决方案3】:

      替代方法:您可能需要考虑使用 trie 而不是哈希表作为字符串字典。

      这种方法的好处是你得到O(|S|)寻找/插入每个字符串的最坏情况复杂性[其中|S|是该字符串的长度]。请注意,哈希表只允许您使用O(|S|) 的平均情况,其中最坏的情况是O(|S|*n) [其中n 是字典的大小]。当负载平衡过高时,trie 也不需要重新散列。

      【讨论】:

        【解决方案4】:

        假设我们没有使用a perfect hash function(你通常没有),哈希告诉你:

        • 如果哈希值不同,则对象不同

        • 如果哈希值相同,则对象可能相同(如果使用了良好的哈希函数),但可能仍然不同。

        所以在哈希表中,冲突将通过一些额外的检查来解决,如果对象实际上是相同的(这会带来一些性能损失,但根据Amdahl's law,你仍然获得了很多,因为冲突很少发生用于良好的散列函数)。在字典中,您只需要解决罕见的碰撞案例并确保取出正确的对象。

        使用另一个不完美的哈希函数不会解决任何问题,它只会减少(另一个)冲突的机会。

        【讨论】:

        • “如果哈希值相同,则对象可能相同” - 仅当元素数不超过哈希桶数时才为真。
        • @TonyDelroy 你是对的,在这种情况下,“可能”和“可能”不是正确的词,因为概率随分布而变化。这就是斜体的原因,但我对此不够具体。
        猜你喜欢
        • 2014-01-12
        • 2015-05-02
        • 2011-09-14
        • 2017-10-03
        • 2021-12-27
        • 1970-01-01
        • 2014-09-28
        • 2013-04-26
        • 1970-01-01
        相关资源
        最近更新 更多