【问题标题】:Hash tables: Open addressing and removing elements哈希表:打开寻址和删除元素
【发布时间】:2011-11-17 23:57:33
【问题描述】:

我试图理解哈希表中的开放寻址,但我的文献中没有回答一个问题。如果使用二次探测,它涉及删除此类哈希表中的元素。然后被移除的元素被一个哨兵元素替换。然后 get() 操作知道它必须走得更远,并且 add() 方法将覆盖它找到的第一个哨兵。但是,如果我想添加一个键已经在哈希表中但在探测路径中的哨兵后面的元素,会发生什么? add() 方法不会用表中已有的相同键覆盖实例的值,而是覆盖哨兵。然后我们在哈希表中有多个具有相同键的元素。我认为这是一个问题,因为它会消耗内存,而且从哈希表中删除元素只会删除其中的第一个,因此仍然可以在表中找到该元素(即它不会被删除)。

因此,在替换哨兵元素之前,似乎有必要在整个探测路径中搜索想要插入的元素的键。我忽略了什么吗?这个问题在实践中是如何处理的?

【问题讨论】:

    标签: hashtable


    【解决方案1】:

    但是如果我想添加一个键为 已经在哈希表中但在探测路径中的哨兵后面? 而不是用相同的键覆盖实例的值 它已经在表中,add() 方法将覆盖 哨兵。

    add() 必须检查探测路径中哨兵之后的每个元素,直到找到一个空元素,正如您稍后指出的那样。如果在探测路径中找不到新元素并且上面有哨兵元素,则可以使用第一个哨兵槽来存储新元素。

    http://www.algolist.net/Data_structures/Hash_table/Open_addressing (HashMap.java) 上有一个哈希表实现。它的put() 方法正是这样做的。 (碰撞分辨率在引用的 sn-p 中是线性探测,但从算法的角度来看,我认为这不是重要的区别。)

    在执行大量删除操作后,表中的标记元素可能过多。对此的解决方案是偶尔重建哈希表(即重新哈希所有内容)(基于项目的数量和哨兵元素的数量)。此操作将消除哨兵元素。

    另一种方法是在删除元素时从探测路径中删除标记 (DELETED) 元素。实际上,在这种情况下,您的表中没有哨兵元素;只有免费和占用的插槽。可能很贵。

    所以似乎有必要在整个探测路径中搜索 在替换哨兵之前要插入的元素的键 元素。

    是的,是的。您必须搜索直到找到一个空元素。

    这个问题在实践中是如何处理的?

    我对现实生活中的哈希表实现了解不多。我想其中很多都可以在互联网上的开源项目中获得。我刚刚检查了 Java 中的 HashtableHashMap 类。两者都使用链接而不是开放寻址。

    【讨论】:

    • 感谢您的回答。我听说 Pythons 字典使用开放寻址。所以我会看看那个。
    【解决方案2】:

    抱歉,回答迟了,但 Java 有一个带有开放寻址的哈希表示例:java.util.IdentityHashMap

    另外,您可以使用 GNU Trove Project。它的映射都是开放寻址哈希表,如其overview page 所述。

    【讨论】:

      猜你喜欢
      • 2011-02-03
      • 1970-01-01
      • 2012-02-25
      • 2019-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-26
      • 1970-01-01
      相关资源
      最近更新 更多