Python:为什么堆会产生不正确的第一次弹出?

时间:2019-02-07 04:10:29

标签: python heap

我正在尝试通过否定列表的所有值来创建最大堆,但是它似乎不起作用:

import heapq
x = range(1,10)
neg = [-n for n in x]
heapq.heappop(neg) # -1
heapq.heappop(neg) # -9
heapq.heappop(neg) # -8

如果可以的话

heapq.heappop(x) # 1
heapq.heappop(x) # 2
heapq.heappop(x) # 3

它似乎正常工作。关于-1为什么返回的任何想法吗?

2 个答案:

答案 0 :(得分:2)

除非首先要维护堆不变式,否则不应该使用heappush/heappop

要从现有列表创建堆,请使用heapq.heapify(mylist)

>>> neg = [-n for n in range(1,10)]
>>> neg[0]  # peek
-1
>>> heapq.heapify(neg)
>>> neg[0]  # peek
-9
>>> -heapq.heappop(neg)  # largest element
9

答案 1 :(得分:0)

heapq.heappop仅对minheaps为 ;您不能仅仅制作一个maxheap并期望基于minheap的函数能够在其上工作,因为它没有观察到minheap不变式。

如果目标是首先弹出-9,则需要通过(有效地O(n))首先对其进行堆化来使堆支持适当的不变式:

heapq.heapify(neg)

之后,您的代码将从-9弹出到-1。

如果您要尝试使用maxheap,则不支持。 All the publically documented heapq functions work with minheaps(添加了重点):

  

以下API与教科书堆算法在两个方面有所不同:(a)我们使用基于零的索引。这使得节点的索引与其子节点的索引之间的关系不太明显,但由于Python使用基于零的索引,因此更适合。 (b)我们的pop方法返回的是最小的项目,而不是最大的项目(在教科书中称为“最小堆”;在文本中,“最大堆”由于适用于就地排序而更为常见)。

该模块中有一些基于maxheap的已选择功能(未记录),这些功能可以正常工作,例如heapq._heappop_max,但它们不是API的文档部分,并且随时可能更改或消失。