Что я использую для реализации max-heap в Python? - PullRequest
168 голосов
/ 23 марта 2010

Python включает модуль heapq для мини-кучи, но мне нужна максимальная куча.Что я должен использовать для реализации max-heap в Python?

Ответы [ 9 ]

164 голосов
/ 23 марта 2010

Самый простой способ - инвертировать значение ключей и использовать heapq. Например, превратить 1000.0 в -1000.0 и 5.0 в -5.0.

160 голосов
/ 13 мая 2014

Вы можете использовать

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
43 голосов
/ 07 ноября 2016

Решение состоит в том, чтобы отрицать ваши значения, когда вы сохраняете их в куче, или инвертировать сравнение объектов следующим образом:

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

Но вы должны помнить, чтобы обернуть и развернуть ваши значения, что требует знания, имеете ли вы дело с min- или max-кучей.

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"
16 голосов
/ 04 июня 2017

Самое простое и идеальное решение

Умножьте значения на -1

Вот, пожалуйста. Все самые высокие цифры теперь самые низкие и наоборот.

Просто помните, что когда вы выталкиваете элемент, умножьте его на -1, чтобы снова получить исходное значение.

4 голосов
/ 23 марта 2010

Если вы вставляете ключи, которые сопоставимы, но не похожи на int, вы можете переопределить операторы сравнения на них (т.е. <= становиться> и> становится <=). В противном случае вы можете переопределить heapq._siftup в модуле heapq (в конце концов, это всего лишь код Python). </p>

3 голосов
/ 11 сентября 2017

Позволяет вам выбрать произвольное количество самых больших или самых маленьких предметов

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]
2 голосов
/ 03 августа 2016

Я реализовал версию 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, за исключением добавления adding _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
0 голосов
/ 11 ноября 2018

Расширение класса 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()
0 голосов
/ 11 июня 2016

Я создал оболочку кучи, которая инвертирует значения, чтобы создать максимальную кучу, а также класс оболочки для минимальной кучи, чтобы сделать библиотеку более похожей на ООП. Здесь - это суть. Есть три класса; 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...