Python:更新heapq中元素的值

时间:2014-08-14 22:47:30

标签: python python-2.7 queue heap priority-queue

如果我的heapq包含一些元素,如:

import heapq


class Element(object):
    def __init__(self, name, val):
        self.name = name
        self.val = val

if __name__ == "__main__":
    heap = []
    e1 = Element('A', 1)
    e2 = Element('B', 65)
    e3 = Element('C', 53)
    e4 = Element('D', 67)
    ...

    heapq.heappush(heap, e1)
    heapq.heappush(heap, e2)
    heapq.heappush(heap, e3)
    heapq.heappush(heap, e4)
    ...

    #IF I want to take elements from the heap and print them I will call:
    while heap:
        new_e = heapq.heappop(heap)
        print new_e.name + ' ' + str(new_e.val)

假设我在堆上有50个元素。我想将元素e3的值从val = 53更改为val = 0.所以这不是堆的顶部元素。我也不想从堆中删除其他元素。 我怎样才能进行这样的更新?

2 个答案:

答案 0 :(得分:0)

这是一个古老的问题,但是如果将来有人看到这个问题并正在寻找答案...

Python3的heapq的新实现包括一些有关如何更新堆元素的有用说明,实际上是将其用作优先级队列。 https://docs.python.org/3.5/library/heapq.html#priority-queue-implementation-notes 本质上,您可以创建一堆元组,Python将基于对元组的顺序比较来评估优先级。由于Python中的堆基本上只是顶部使用了heapq接口的标准列表,因此文档建议您使用一个附加的字典,该字典将堆值映射到堆(列表)中的索引。

对于您的原始问题:

  

假设堆上有50个元素。我想改变价值   e3元素从val = 53到val = 0的关系。因此,这不是顶部元素   堆。我也不想从堆中删除其他元素。   我该如何进行更新?

按照上述逻辑更新堆中元素的基本步骤是:

  • 检查字典以获取要更新的元素的索引(在检查元素是否在字典+相应的堆中之后)
  • 更新堆中的值
  • 调用在O(N)中运行的heapq.heapify(heap)。另外,如果您知道更新会将值更新+/- 1,则可以将要更新的元素的位置替换为其上方或下方的位置。

编辑:这是一个类似的问题,有更多答案:How to update elements within a heap? (priority queue)

答案 1 :(得分:-1)

由于没有输出,因此很难运行代码。但是,我尝试了一些事情:

在heapq模块中,heap[0]始终被指定为最小的项目。在您的情况下,1是最小的项目。因此,从理论上讲,将此值从1更改为5应该很容易。我试过heapq.heappop(heap),它应该返回最小的值。因此,正如你在你的问题中所说的那样,“我想更新元素的val我不知道反过来是什么”,这种方法会自动获得最小的值(我假设您的问题是要替换1因为它是最小的值,因为它与名称First结合在一起)但是,当我尝试自己运行代码时,我收到了<__main__.Element object at 0x103c15dd0>所以你应该尝试修改代码以便打印输出同样的事情是print heap[0],同样的错误类型。然后,一旦您不再收到此类错误,请在代码块结束时尝试:

s = heapq.heappop(heap)

print heapq.heapreplace(5, s)

使用此方法,我收到以下错误:TypeError: heap argument must be a list 因此,如果您可以弄清楚如何将s转换为列表,那么这应该可行。也许有人可以编辑我的答案来添加此代码。

希望这有帮助。

SELF-编辑:

将此添加到代码块的末尾,[]将其转换为列表,这是heapq想要输入的内容。

s = heapq.heappop(heap)

print heapq.heapreplace([5], [s])

这将返回输出中的值5。

回到输出问题,如果您指定了想要输出的内容,我可以尝试为您提供更多帮助。