最简单的方法是反转键的值并使用heapq模块。例如,将1000.0转换为-1000.0,将5.0转换为-5.0。
import heapq
listForTree = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
heapq.heapify(listForTree) # for a min heap
heapq._heapify_max(listForTree) # for a maxheap!!
如果你想要弹出元素,可以使用以下代码:
heapq.heappop(minheap) # pop from minheap
heapq._heappop_max(maxheap) # pop from maxheap
解决方法是在将值存储到堆中时对其取反,或者倒转对象比较,如下所示:
import heapq
class MaxHeapObj(object):
def __init__(self, val): self.val = val
def __lt__(self, other): return self.val > other.val
def __eq__(self, other): return self.val == other.val
def __str__(self): return str(self.val)
最大堆的示例:
maxh = []
heapq.heappush(maxh, MaxHeapObj(x))
x = maxh[0].val # fetch max value
x = heapq.heappop(maxh).val # pop max value
但是你必须记得包装和解包装你的值,这需要知道你是否正在处理最小堆还是最大堆。
添加MinHeap
和MaxHeap
对象的类可以简化您的代码:
class MinHeap(object):
def __init__(self): self.h = []
def heappush(self, x): heapq.heappush(self.h, x)
def heappop(self): return heapq.heappop(self.h)
def __getitem__(self, i): return self.h[i]
def __len__(self): return len(self.h)
class MaxHeap(MinHeap):
def heappush(self, x): heapq.heappush(self.h, MaxHeapObj(x))
def heappop(self): return heapq.heappop(self.h).val
def __getitem__(self, i): return self.h[i].val
使用示例:
minh = MinHeap()
maxh = MaxHeap()
# add some values
minh.heappush(12)
maxh.heappush(12)
minh.heappush(4)
maxh.heappush(4)
# fetch "top" values
print(minh[0], maxh[0]) # "4 12"
# fetch and remove "top" values
print(minh.heappop(), maxh.heappop()) # "4 12"
list
参数到__init__,如果有这个参数,我会调用heapq.heapify
方法,并且还增加了一个heapreplace
方法。 - Boobooheapify
实现以及您想要对堆执行什么操作。我们只需要定义 __lt__
和 __eq__
来方便所有 MaxHeapObj
对象之间的比较(<、<=、==、>、>=),这在搜索堆时可能是必需的。 - Isaac Turner将数值乘以-1
这样做后,所有最大的数字现在都是最小的,反之亦然。
只需记住,当您弹出一个元素时,要将其乘以-1以获得原始值。
最简单的方法是将每个元素转换为负数,这样就可以解决您的问题。
import heapq
heap = []
heapq.heappush(heap, 1*(-1))
heapq.heappush(heap, 10*(-1))
heapq.heappush(heap, 20*(-1))
print(heap)
输出结果将会是:
[-20, -1, -10]
我实现了一个max-heap版本的heapq,并将其提交到了PyPI。这只是对heapq模块的CPython代码进行了微小的更改。
Heapq_max (GitHub)
安装
pip install heapq_max
使用方法
简而言之:与heapq模块相同,只是在所有函数后添加“_max”。
heap_max = [] # Creates an empty heap
heappush_max(heap_max, item) # Pushes a new item on the heap
item = heappop_max(heap_max) # Pops the largest item from the heap
item = heap_max[0] # The largest item on the heap without popping it
heapify_max(x) # Transforms the list into a heap, in-place, in linear time
item = heapreplace_max(heap_max, item) # Pops and returns the largest item, and
# adds a new item; the heap size is unchanged
我也需要使用一个最大堆,而且我处理的是整数,所以我只需将我从 heap
需要的两个方法包装如下:
import heapq
def heappush(heap, item):
return heapq.heappush(heap, -item)
def heappop(heap):
return -heapq.heappop(heap)
然后我只需将heapq.heappush()
和heapq.heappop()
函数调用替换为分别调用heappush()
和heappop()
函数。
import heapq
from typing import List
class MaxHeap:
def __init__(self):
self.data = []
def top(self):
return -self.data[0]
def push(self, val):
heapq.heappush(self.data, -val)
def pop(self):
return -heapq.heappop(self.data)
使用方法:
max_heap = MaxHeap()
max_heap.push(3)
max_heap.push(5)
max_heap.push(1)
print(max_heap.top()) # 5
最简单的方法:
from heapq import *
h = [5, 7, 9, 1, 3]
h_neg = [-i for i in h]
heapify(h_neg) # heapify
heappush(h_neg, -2) # push
print(-heappop(h_neg)) # pop
# 9
如果您要插入可比较但不类似于int的键,您可能会覆盖它们上的比较运算符(即 <= 变为 >,> 变为 <=)。否则,您可以在heapq模块中覆盖heapq._siftup函数(归根结底,这都是Python代码)。
# If available, use C implementation
),它恰好执行了该注释所描述的功能。 - tzot
heapq
没有提供反向排序的功能。 - shabbychefheapq
没有提供这个功能,而且也没有好的替代方法。 - ire_and_cursesint
/float
的内容,您可以通过将它们包装在一个具有反向__lt__
运算符的类中来反转排序顺序。 - Daniel Stutzbach