【问题标题】:How to remove a specific element in a heap without losing heap properties in Python?python - 如何在不丢失堆属性的情况下删除堆中的特定元素?
【发布时间】:2018-04-12 23:09:18
【问题描述】:

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

【问题讨论】:

  • 你指的是什么堆的实现?如果它包含remove 运算符(表示对堆元素的显式访问),它也可能包含change priority 一个。
  • @MBo 在 Python 中,明显的实现是标准库中的 heapq。

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


【解决方案1】:

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

Move the last item in the heap to the position that contains the item to remove.
Decrement heap count.
If the item is smaller than its parent
    bubble it up the heap
else
    sift it down the heap

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

一个有效的解决方案是创建一个包含项目键的字典,值是该项目在堆中的索引。但是,您必须维护字典:

  1. 向堆中插入项目时,添加字典条目
  2. 从堆中删除项目时,删除字典条目
  3. 每当您更改某个项目在堆中的位置时,都会更新该项目在字典中的值。

使用该字典,您可以 O(1) 访问堆中项目的位置,并且可以在 O(log n) 中删除它。

【讨论】:

    【解决方案2】:

    我会让每个元素成为一个数据结构,并带有一个是否忽略它的标志。当你 heappop 时,如果它是一个被标记的元素,你只会再次弹出。这非常简单,显而易见,并且对堆内部的工作方式一无所知。例如,您不需要知道元素在堆中的实际位置来标记它。

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

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

    【讨论】:

      【解决方案3】:

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

      将您需要删除的索引/指针上的数字替换为其最大的数字 子并递归地重复该过程(用最大的子节点替换子节点等),直到您到达一个没有子节点的节点,您可以轻松将其删除。

      这个算法的复杂度是O(log n)。

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

      【讨论】:

        猜你喜欢
        • 2013-11-07
        • 2021-05-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-06
        • 2013-01-21
        • 2012-04-27
        • 1970-01-01
        相关资源
        最近更新 更多