Python包含了用于min-堆的heapq模块,但我需要一个max堆。在Python中我应该使用什么来实现最大堆?
当前回答
最简单最理想的解决方案
将这些值乘以-1
好了。所有最高的数字现在都是最低的,反之亦然。
只要记住,当您弹出一个元素与-1相乘以再次获得原始值时。
其他回答
我创建了一个堆包装器,它将值颠倒以创建max-heap,还为min-heap创建了一个包装器类,以使库更像oop。这是要点。有三个班级;Heap(抽象类),HeapMin和HeapMax。
方法:
isempty() -> bool; obvious
getroot() -> int; returns min/max
push() -> None; equivalent to heapq.heappush
pop() -> int; equivalent to heapq.heappop
view_min()/view_max() -> int; alias for getroot()
pushpop() -> int; equivalent to heapq.pushpop
为了详细说明https://stackoverflow.com/a/59311063/1328979,这里有一个针对一般情况的完整文档、注释和测试的Python 3实现。
from __future__ import annotations # To allow "MinHeap.push -> MinHeap:"
from typing import Generic, List, Optional, TypeVar
from heapq import heapify, heappop, heappush, heapreplace
T = TypeVar('T')
class MinHeap(Generic[T]):
'''
MinHeap provides a nicer API around heapq's functionality.
As it is a minimum heap, the first element of the heap is always the
smallest.
>>> h = MinHeap([3, 1, 4, 2])
>>> h[0]
1
>>> h.peek()
1
>>> h.push(5) # N.B.: the array isn't always fully sorted.
[1, 2, 4, 3, 5]
>>> h.pop()
1
>>> h.pop()
2
>>> h.pop()
3
>>> h.push(3).push(2)
[2, 3, 4, 5]
>>> h.replace(1)
2
>>> h
[1, 3, 4, 5]
'''
def __init__(self, array: Optional[List[T]] = None):
if array is None:
array = []
heapify(array)
self.h = array
def push(self, x: T) -> MinHeap:
heappush(self.h, x)
return self # To allow chaining operations.
def peek(self) -> T:
return self.h[0]
def pop(self) -> T:
return heappop(self.h)
def replace(self, x: T) -> T:
return heapreplace(self.h, x)
def __getitem__(self, i) -> T:
return self.h[i]
def __len__(self) -> int:
return len(self.h)
def __str__(self) -> str:
return str(self.h)
def __repr__(self) -> str:
return str(self.h)
class Reverse(Generic[T]):
'''
Wrap around the provided object, reversing the comparison operators.
>>> 1 < 2
True
>>> Reverse(1) < Reverse(2)
False
>>> Reverse(2) < Reverse(1)
True
>>> Reverse(1) <= Reverse(2)
False
>>> Reverse(2) <= Reverse(1)
True
>>> Reverse(2) <= Reverse(2)
True
>>> Reverse(1) == Reverse(1)
True
>>> Reverse(2) > Reverse(1)
False
>>> Reverse(1) > Reverse(2)
True
>>> Reverse(2) >= Reverse(1)
False
>>> Reverse(1) >= Reverse(2)
True
>>> Reverse(1)
1
'''
def __init__(self, x: T) -> None:
self.x = x
def __lt__(self, other: Reverse) -> bool:
return other.x.__lt__(self.x)
def __le__(self, other: Reverse) -> bool:
return other.x.__le__(self.x)
def __eq__(self, other) -> bool:
return self.x == other.x
def __ne__(self, other: Reverse) -> bool:
return other.x.__ne__(self.x)
def __ge__(self, other: Reverse) -> bool:
return other.x.__ge__(self.x)
def __gt__(self, other: Reverse) -> bool:
return other.x.__gt__(self.x)
def __str__(self):
return str(self.x)
def __repr__(self):
return str(self.x)
class MaxHeap(MinHeap):
'''
MaxHeap provides an implement of a maximum-heap, as heapq does not provide
it. As it is a maximum heap, the first element of the heap is always the
largest. It achieves this by wrapping around elements with Reverse,
which reverses the comparison operations used by heapq.
>>> h = MaxHeap([3, 1, 4, 2])
>>> h[0]
4
>>> h.peek()
4
>>> h.push(5) # N.B.: the array isn't always fully sorted.
[5, 4, 3, 1, 2]
>>> h.pop()
5
>>> h.pop()
4
>>> h.pop()
3
>>> h.pop()
2
>>> h.push(3).push(2).push(4)
[4, 3, 2, 1]
>>> h.replace(1)
4
>>> h
[3, 1, 2, 1]
'''
def __init__(self, array: Optional[List[T]] = None):
if array is not None:
array = [Reverse(x) for x in array] # Wrap with Reverse.
super().__init__(array)
def push(self, x: T) -> MaxHeap:
super().push(Reverse(x))
return self
def peek(self) -> T:
return super().peek().x
def pop(self) -> T:
return super().pop().x
def replace(self, x: T) -> T:
return super().replace(Reverse(x)).x
if __name__ == '__main__':
import doctest
doctest.testmod()
https://gist.github.com/marccarre/577a55850998da02af3d4b7b98152cf4
最简单最理想的解决方案
将这些值乘以-1
好了。所有最高的数字现在都是最低的,反之亦然。
只要记住,当您弹出一个元素与-1相乘以再次获得原始值时。
解决方案是当你在堆中存储你的值时对其求反,或者像这样反转你的对象比较:
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)
max-heap的例子:
maxh = []
heapq.heappush(maxh, MaxHeapObj(x))
x = maxh[0].val # fetch max value
x = heapq.heappop(maxh).val # pop max value
但是您必须记住包装和打开您的值,这需要知道您正在处理的是最小堆还是最大堆。
MinHeap, MaxHeap类
为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"
heapq模块拥有实现maxheap所需的一切。 它只做max-heap的堆推功能。 我已在下面示范如何克服这一点
在heapq模块中添加这个函数:
def _heappush_max(heap, item):
"""Push item onto heap, maintaining the heap invariant."""
heap.append(item)
_siftdown_max(heap, 0, len(heap)-1)
最后加上这句话:
try:
from _heapq import _heappush_max
except ImportError:
pass
瞧!这是完成了。
PS -转到heapq函数。首先在编辑器中写入“import heapq”,然后右键单击“heapq”并选择转到定义。
推荐文章
- 为什么我得到“'str'对象没有属性'读取'”当尝试使用' json。载入字符串?
- 不区分大小写的列表排序,没有降低结果?
- 排序后的语法(key=lambda:…)
- 在烧瓶中返回HTTP状态代码201
- 使用python创建一个简单的XML文件
- APT命令行界面式的yes/no输入?
- 如何打印出状态栏和百分比?
- 在Python中获取大文件的MD5哈希值
- 在Python格式字符串中%s是什么意思?
- 如何循环通过所有但最后一项的列表?
- 如何有效地清除std::queue ?
- python用什么方法避免默认参数为空列表?
- ValueError: numpy。Ndarray大小改变,可能表示二进制不兼容。期望从C头得到88,从PyObject得到80
- Anaconda /conda -安装特定的软件包版本
- 我在哪里调用Keras的BatchNormalization函数?