Data structures 哈希表上的延迟删除

Data structures 哈希表上的延迟删除,data-structures,hashtable,Data Structures,Hashtable,在我的实现中,我使用延迟删除和线性或二次探测来解决冲突。对于插入,当遇到延迟删除的项目时,我会将其替换为要插入的项目。这样做的缺点或不正确之处是什么(对于线性或二次或双哈希冲突解决方案)?难道它不节省空间吗?开放寻址哈希表的问题是,它们的性能会随着时间的推移而下降,尤其是当条目非常动态时 例如,让我们考虑一个简单的线性探索列表。如果哈希槽1上有3个冲突,则将使用槽1、2、3。如果2被删除,您需要将其标记为“以前使用过”,以便仍然能够在插槽3中找到该项目。在某些使用模式下,这将使哈希表降级到线性搜

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

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

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

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

这样,如果您有几乎恒定的键,则使用开放式寻址,否则考虑关闭的地址哈希表。


对于某些问题,您可能还需要研究布谷鸟哈希等其他概念

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

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
功能删除(按键)
i:=查找槽(键)
如果插槽[i]未被占用
return//key不在表中
j:=i
环
j:=(j+1)模数槽
如果插槽[j]未被占用
出口回路
k:=散列(槽[j].key)模num\u槽
如果(j>i和(kj))或
(j
在那一页上也有一些参考文献。我相信这与插入具有完全相同的性能特征,并将表恢复到与从未添加条目一样好的状态

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