2009-03-24 12 views
10

Vorrei memorizzare un set di oggetti in un heap minimo definendo una funzione di confronto personalizzata. Vedo che c'è un modulo heapq disponibile come parte della distribuzione python. C'è un modo per usare un comparatore personalizzato con questo modulo? In caso contrario, qualcun altro ha creato un heap minimo personalizzato?min heap in python

+0

Per un frammento più confortevole - (e Python 3 pronto), controllare la mia risposta a http://stackoverflow.com/questions/8875706/python-heapq-with-custom-compare-predicate/8875823#8875823 – jsbueno

risposta

13

Sì, c'è un modo. Definisci una classe di wrapping che implementa il tuo comparatore personalizzato e utilizza un elenco di quelli al posto di un elenco dei tuoi oggetti reali. Questo è quanto di meglio ci sia mentre si usa ancora il modulo heapq, poiché non fornisce argomenti key = o cmp = come le funzioni/metodi di ordinamento.

def gen_wrapper(cmp): 
    class Wrapper(object): 
     def __init__(self, value): self.value = value 
     def __cmp__(self, obj): return cmp(self.value, obj.value) 
    return Wrapper 
+2

Nota che questo non funzionerà con python 3.0, che elimina __cmp__. –

+0

No, non funzionerà in Python 3.0, ma non importa, perché in Python 3.0 manca l'intero concetto di "funzione comparatore". La domanda semplicemente non si applica in quel caso. –

+4

Um. Dovresti definire __le__ piuttosto che __cmp__. Ciò manterrebbe la compatibilità con Python 2/3. Dopo tutto, le operazioni heapq e le operazioni di ordinamento utilizzano <= come funzione di confronto. – tzot

15

due opzioni (a parte il suggerimento di Devin Jeanpierre):

  1. Decora i tuoi dati prima di utilizzare l'heap. Questo è l'equivalente dell'opzione key= all'ordinamento. per esempio. se (per qualche motivo) voleva heapify un elenco di numeri in base alla loro sine:

    data = [ # list of numbers ] 
    heap = [(math.sin(x), x) for x in data] 
    heapq.heapify(heap) 
    # get the min element 
    item = heappop(heap)[1] 
    
  2. Il modulo heapq è implementato in puro Python. Potresti semplicemente copiarlo nella tua directory di lavoro e cambiare i bit rilevanti. Da un rapido sguardo, dovresti modificare siftdown() e siftup(), e probabilmente nlargest e nsmallest se ne hai bisogno.

+0

+1: decora i tuoi dati. –

+1

Inoltre, il modulo heapq è implementato sia in C che in Python. L'importazione di heapq utilizza il modulo C, se disponibile. – tzot

+0

Ah, hai ragione. Bene, la cosa importante per il mio secondo suggerimento è che il codice python è disponibile nella directory lib se vuoi eseguire il rollover. –