【问题标题】:Lazy deletion on hash tables哈希表的延迟删除
【发布时间】:2012-11-15 20:42:48
【问题描述】:

在我的实现中,我使用延迟删除和线性或二次探测来解决冲突。对于插入,当我遇到延迟删除的项目时,我将其替换为要插入的项目。这样做有什么缺点或不正确(对于线性或二次或双哈希冲突解决方案)?不省空间吗?

【问题讨论】:

    标签: data-structures hashtable


    【解决方案1】:

    开放寻址哈希表的问题在于它们的性能会随着时间的推移而下降,尤其是当条目非常动态时。

    例如,让我们考虑一个简单的线性探测列表。如果您在哈希槽 1 上发生 3 次冲突,则将使用槽 1、2、3。如果 2 被删除,您需要将其标记为“以前使用过”才能在插槽 3 中找到该项目。在某些使用模式下,这会将您的哈希表降级到线性搜索时间越来越长的地步,需要代价高昂的重新调整以使其再次生效。

    在插入/删除大量项目时,随着时间的推移,关闭地址的哈希表的性能将更加稳定。但它们对缓存并不友好,因为您必须摆弄指针。

    因此,如果您有几乎不变的键,请使用开放寻址,否则考虑使用封闭寻址哈希表。

    对于某些问题,您可能还想研究其他概念,例如布谷鸟哈希。

    【讨论】:

      【解决方案2】:

      无需从线性探测的开放寻址哈希表中进行延迟删除。硬删除可以简单地在恒定时间内完成,而无需表降级。多年来,维基百科哈希表页面上都有它的伪代码。我不知道为什么不再存在,但这里有一个永久链接,可以追溯到它以前的时间:Old Wikipedia Hash Table page,为了您的方便,这里是伪代码:

      function remove(key)
       i := find_slot(key)
       if slot[i] is unoccupied
           return   // key is not in the table
       j := i
       loop
           j := (j+1) modulo num_slots
           if slot[j] is unoccupied
               exit loop
           k := hash(slot[j].key) modulo num_slots
           if (j > i and (k <= i or k > j)) or
              (j < i and (k <= i and k > j)) (note 2)
               slot[i] := slot[j]
               i := j
       mark slot[i] as unoccupied
      

      该页面上还有一些real code 的参考。我相信这与插入具有完全相同的性能特征,并将表恢复到与从未添加条目一样好的状态。

      这种删除方法比常用的“标记已删除并偶尔重新散列所有内容”要好,因为上述方法是常数时间而不是摊销常数时间。如果您有一个包含一百万个要添加和删除的项目的哈希表,在“标记已删除”方法中,偶尔的添加或删除将比之前和之后的时间长一百万倍 - 这不是良好的性能特点。

      【讨论】:

        猜你喜欢
        • 2019-03-31
        • 2013-09-17
        • 2021-06-01
        • 2023-04-10
        • 2018-11-17
        • 1970-01-01
        • 2014-06-24
        • 2019-04-17
        • 2017-07-17
        相关资源
        最近更新 更多