如何删除堆中的特定元素而不丢失Python中的堆属性?

时间:2017-10-31 17:26:32

标签: python algorithm python-3.x heap priority-queue

我正在尝试实现一种算法来解决天际线问题,该问题涉及从最大堆中间删除特定元素。我目前的方式是maxheap.remove(index),但我必须跟进heapify(maxheap),否则订单会被取消。我知道在java中你可以使用类似treemap的东西来做到这一点。无论如何在python中比调用两个单独的方法更有效地做到这一点,每个方法花费O(n)时间?

3 个答案:

答案 0 :(得分:0)

我希望每个元素都是一个数据结构,带有一个标志,用于是否忽略它。当你进行heappop时,如果它是被标记的元素,你将再次弹出。这非常简单,明显,并且无法了解堆内部的工作原理。例如,您不需要知道元素实际位于堆中的位置以标记它。

这种方法的缺点是标记的元素会随着时间的推移而累积。有时您可以将它们过滤掉然后堆积。

如果此解决方案不足以满足您的需求,您应该在Python中寻找某种btree实现。这将像您在Java中习惯的树形图一样。

答案 1 :(得分:0)

从堆中删除任意项是O(log n)操作,前提是您知道该项在堆中的位置。算法是:

'images' => [
  [
    'src' => 'https://www.example.com/uploads/image/'.$product['image'],
    'title' => $product['name'],
    'alt' => $product['name'],
    'position' => 0
  ]
],

主要问题是找到项目在堆中的位置。正如您所指出的那样,除非您保留更多信息,否则这样做是O(n)操作。

对此有效的解决方案是创建包含项键的字典,值是堆中该项的索引。但是,你必须维护字典:

  1. 将项目插入堆中时,添加字典条目
  2. 从堆中删除项目时,请删除字典条目
  3. 每当您更改堆中项目的位置时,请更新该项目在字典中的值。
  4. 使用该字典,您可以O(1)访问堆中项目的位置,并且可以在O(log n)中删除它。

答案 2 :(得分:0)

是的,有一种更有效的方法 - 如果你有索引或指针(取决于实现方法)。

将要删除的索引/指针上的数字替换为最大的数字 child并以递归方式重复该过程(将子项替换为其最大的子项等等),直到找到没有子项的节点,然后轻松删除。

该算法的复杂性为O(log n)。

http://algorithms.tutorialhorizon.com/binary-min-max-heap/