如果多个删除的元素具有相同的值,则黑名单集会出现问题。而是heap_remove
使用 tombstone-counting-dict 实现:
def heap_remove(heap, value):
tombstones[value] = tombstones.get(value, 0) + 1
while len(heap) and heap[0] in tombstones and tombstones[heap[0]]:
heappop(heap)
正如预期的那样,您已经摊销了 O(1) 删除时间,并且top
只要您不在popping
其他地方的堆中,您的堆总是准确的。
考虑一下这个数字列表,它们首先被全部推入堆中,然后以相同的顺序“删除”(不弹出):
[3、3、2、7、1、4、2]
插入按预期工作:
After inserting 3 into heap, top = 3
After inserting 3 into heap, top = 3
After inserting 2 into heap, top = 2
After inserting 7 into heap, top = 2
After inserting 1 into heap, top = 1
After inserting 4 into heap, top = 1
After inserting 2 into heap, top = 1
但是删除是通过增加对象的墓碑来完成的。如果堆的顶部设置了墓碑,则移除该对象并减少墓碑计数器。
Called remove( 3 )
Marking 3 for deletion
Called remove( 3 )
Marking 3 for deletion
Called remove( 2 )
Marking 2 for deletion
Called remove( 7 )
Marking 7 for deletion
Called remove( 1 )
Marking 1 for deletion
Deleting top 1
Updated heap is: [2, 2, 3, 7, 3, 4]
Deleting top 1
Updated heap is: [2, 3, 3, 7, 4]
Called remove( 4 )
Marking 4 for deletion
Called remove( 2 )
Marking 2 for deletion
Deleting top 2
Updated heap is: [3, 3, 4, 7]
Deleting top 3
Updated heap is: [3, 7, 4]
Deleting top 3
Updated heap is: [4, 7]
Deleting top 4
Updated heap is: [7]
Deleting top 7
Updated heap is: []
请注意,当第二个heap_remove(3)
被称为@GP89 的解决方案时,就像3
在墓碑集中一样。
您可以在此处探索此示例。