Gemäß der Heapq-Dokumentation besteht die Möglichkeit, die Heap-Reihenfolge anzupassen, darin, dass jedes Element auf dem Heap ein Tupel ist, wobei das erste Tupelelement eines ist, das normale Python-Vergleiche akzeptiert.
Die Funktionen im Heapq-Modul sind etwas umständlich (da sie nicht objektorientiert sind) und erfordern immer, dass unser Heap-Objekt (eine Heapified-Liste) explizit als erster Parameter übergeben wird. Wir können zwei Fliegen mit einer Klappe schlagen, indem wir eine sehr einfache Wrapper-Klasse erstellen, mit der wir eine key
Funktion angeben und den Heap als Objekt präsentieren können.
Die folgende Klasse führt eine interne Liste, in der jedes Element ein Tupel ist, dessen erstes Mitglied ein Schlüssel ist, der zum Zeitpunkt des Einfügens des Elements unter Verwendung des key
Parameters berechnet wird und bei der Heap-Instanziierung übergeben wird:
import heapq
class MyHeap(object):
def __init__(self, initial=None, key=lambda x:x):
self.key = key
self.index = 0
if initial:
self._data = [(key(item), i, item) for i, item in enumerate(initial)]
self.index = len(self._data)
heapq.heapify(self._data)
else:
self._data = []
def push(self, item):
heapq.heappush(self._data, (self.key(item), self.index, item))
self.index += 1
def pop(self):
return heapq.heappop(self._data)[2]
(Der zusätzliche self.index
Teil besteht darin, Konflikte zu vermeiden, wenn der ausgewertete Schlüsselwert ein Unentschieden ist und der gespeicherte Wert nicht direkt vergleichbar ist. Andernfalls könnte heapq mit TypeError fehlschlagen.)