Hash 解决哈希字符串中冲突的最佳方法

Hash 解决哈希字符串中冲突的最佳方法,hash,Hash,我在一次面试中被问到这个问题,说用第二个有作用,但面试官一直在问我其他的答案。有其他解决方案吗?使用链表作为散列桶。因此,任何冲突都会得到优雅的处理。另一种方法:您可能希望对字符串字典使用concider而不是哈希表 这种方法的优点是,查找/插入每个字符串(其中| S |是该字符串的长度)会得到O(| S |)最坏情况下的复杂性。请注意,哈希表只允许使用O(| S |)的平均情况,其中最坏的情况是O(| S |*n)[其中n是字典的大小]。当负载平衡过高时,trie也不需要重新灰化。假设我们没有

我在一次面试中被问到这个问题,说用第二个有作用,但面试官一直在问我其他的答案。有其他解决方案吗?

使用链表作为散列桶。因此,任何冲突都会得到优雅的处理。

另一种方法:您可能希望对字符串字典使用concider而不是哈希表

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

假设我们没有使用(您通常没有),哈希会告诉您:

  • 如果散列不同,则对象不同


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

因此,在哈希表中,冲突将通过一些额外的检查来解决,如果对象实际上相同或不同(这会带来一些性能损失,但根据,您仍然获得了很多,因为对于好的哈希函数,冲突很少发生)。在字典中,您只需要解决这种罕见的碰撞情况,并确保找到正确的对象

使用另一个非完美散列函数不会解决任何问题,它只是减少了(另一个)冲突的机会

解决哈希字符串中冲突的最佳方法 “连续插入”

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

  • 使用置换列表,因此可以尝试从 散列到bucket,直到找到一个空闲的bucket(按表修改) 尺寸)。置换列表可能看起来像{3,5,11, 19…}等等-理想情况下,您希望 位移不是一系列其他位移的总和
  • 使用不同的算法进行重新灰化(但是你还需要另一种算法) 算法(如果发生两次碰撞等)
  • 根目录中的容器 桶,以便可以搜索碰撞的字符串。典型的 铲斗的数量应类似于或大于 元素的数量,因此每个桶中的元素将相当小且 通过数组/向量进行暴力搜索是合理的选择 方法,但链表也是可信的

  • 比较这些,置换列表往往最快(因为添加一个偏移量比计算另一个散列或支持单独的堆和分配更便宜,并且在大多数情况下,前一个或两个置换(可以通过少量存储桶合理地进行)足以找到一个空存储桶,因此内存使用的位置是合理的)尽管它们比另一种散列算法更容易发生冲突(这种算法应该接近#elements/#bucket,以避免进一步的冲突)。对于置换列表和重新灰化,您必须提供足够的重试次数,以确保在实践中不会出现完全失败,不会添加一些最后的失败处理,也不会接受可能发生的失败。

    链接会使每个节点消耗一个指针,并以丢失引用位置为代价解决所有问题。(二次散列也会丢失)散列的目的是什么?密码?MD5文件哈希?字典/哈希集?@Darjan for dictionariesFixed Dictionaries(无插入/删除)?“如果哈希相同,则对象可能相同”-仅当元素数不超过哈希桶数时才为真。@TonyDelroy你说得对,在这种情况下,“可能”和“可能”不是正确的词,因为概率随分布而变化。这就是为什么要用斜体字,但我对此不够具体。