Python включает модуль heapq для мини-кучек, но мне нужна максимальная куча. Что я должен использовать для реализации max-heap в Python?
Что я использую для реализации max-heap в Python?
Ответ 1
Самый простой способ - инвертировать значение ключей и использовать heapq. Например, включите 1000.0 в -1000.0 и 5.0 в -5.0.
Ответ 2
Ты можешь использовать
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
Ответ 3
Решение состоит в том, чтобы отрицать ваши значения, когда вы храните их в куче, или инвертируйте сравнение объектов следующим образом:
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,MaxHeapInt(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"
Ответ 4
Самое простое и идеальное решение
Умножьте значения на -1
Вот и ты. Все самые высокие цифры теперь самые низкие и наоборот.
Просто помните, что когда вы выталкиваете элемент, чтобы умножить его на -1, чтобы снова получить исходное значение.
Ответ 5
Если вы вставляете ключи, сопоставимые, но не int-like, вы можете потенциально переопределить операторы сравнения на них (т.е. <= стать > и > становится < =). В противном случае вы можете переопределить heapq._siftup в модуле heapq (все это просто код Python, в конце).
Ответ 6
Позволяет выбрать произвольное количество самых больших или наименьших элементов
import heapq
heap = [23, 7, -4, 18, 23, 42, 37, 2, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]
heapq.heapify(heap)
print(heapq.nlargest(3, heap)) # [42, 42, 37]
print(heapq.nsmallest(3, heap)) # [-4, -4, 2]
Ответ 7
Я реализовал версию heapq с максимальной загрузкой и отправил ее в PyPI. (Очень небольшое изменение кода CPython модуля heapq.)
https://pypi.python.org/pypi/heapq_max/
https://github.com/he-zhe/heapq_max
Установка
pip install heapq_max
Использование
tl; dr: тот же, что и модуль 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] # largest item on the heap without popping it
heapify_max(x) # transforms list into a heap, in-place, in linear time
item = heapreplace_max(heap_max, item) # pops and returns largest item, and
# adds new item; the heap size is unchanged
Ответ 8
Я создал оболочку кучи, которая инвертирует значения для создания max-heap, а также класс-оболочку для мини-кучи, чтобы сделать библиотеку более похожей на OOP. Здесь суть. Есть три класса; Куча (абстрактный класс), 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
Ответ 9
Расширение класса int и переопределение __lt__ - один из способов.
import queue
class MyInt(int):
def __lt__(self, other):
return self > other
def main():
q = queue.PriorityQueue()
q.put(MyInt(10))
q.put(MyInt(5))
q.put(MyInt(1))
while not q.empty():
print (q.get())
if __name__ == "__main__":
main()