2010-07-14 16 views
5

Sto cercando una struttura di dati efficiente per rappresentare una lista di priorità. Nello specifico, devo assegnare una priorità a un insieme di elementi e restituire solo gli elementi con il punteggio più alto. Ho esaminato le code di priorità che funzionano su heap, ma non sembrano adattarsi alle mie esigenze. Riorganizzeranno la struttura dell'heap non appena eseguirò il polling dell'elemento di valutazione superiore dalla coda.Lista di priorità efficiente

La soluzione più semplice sarebbe ovviamente una lista collegata, che nel peggiore dei casi sarebbe necessario molto tempo per l'operazione di inserimento.

Qualcuno ha una soluzione migliore?

+0

Quanti elementi? Sono persistiti ovunque, se sì, come? – Lazarus

+5

Ulteriori informazioni sull'efficacia desiderata * inserimento *, * recupero * (di elementi prioritari) e * rimozione * in relazione tra loro. – Artelius

+0

Desidero valutare prima gli elementi e quindi ritirare i primi x elementi con punteggio superiore nell'ordine corretto. Quindi, dato che ci sono molti inserimenti, l'inserimento dovrebbe essere piuttosto efficiente. Il retrival potrebbe essere meno efficiente. – ladi

risposta

4

Cumuli sembrano molto adatto, e sembra che si sta andando su di esso in modo sbagliato.

detto che volevi gli elementi x top (come fa questo x confronta con n, btw?)

Quello che state facendo è mettere tutto in un max-heap e ottenere la x in alto.

Suggerisco, invece, di utilizzare un min-heap di esattamente x elementi.

I primi x elementi inseriti nell'heap.

Elemento successivo in entrata, si confronta con il minimo che può essere eseguito molto rapidamente (O (1) volta) nell'heap. Se è più piccolo, ignori semplicemente l'elemento in entrata.

Se l'elemento in entrata è più grande di min, quindi si aumenta il minimo per l'elemento in entrata e lo si spazia in basso nell'heap. Questo dovrebbe essere il momento logx nel peggiore dei casi.

Una volta fatto (nel tempo nlogx), è possibile recuperare gli elementi dal mucchio in modo ordinato in O (xlogx) tempo.

A seconda di come i dati sono al (e quanto piccolo x è), utilizzando questa soluzione min-heap può essere veramente veloce.


Se davvero vuole veramente gli inserti di essere super-veloce e non si preoccupano molto circa il recupero allora si può anche effettuare le seguenti operazioni.

inserire gli elementi in un vettore (array con O ammortizzato (1) inserire tempo) nell'ordine vengono.

L'uso l'algoritmo di selezione per trovare l'elemento X più grande (in O (n), ma le costanti potrebbero essere grande). Dire che il numero è S.

Ora piedi la matrice si confrontano ogni elemento con S e selezionare quelli grandi come S.

Se x è di dimensioni ragionevoli e paragonabile a n (come n/2 o qualcosa del genere) questo potrebbe funzionare bene, ma se x è piccolo rispetto a n, suggerirei di andare con il min-heap.

+0

Non ci ho pensato in questo modo. Questo sembra molto promettente. – ladi

4

Hmm. Skip lists? Dovrebbero avere l'inserimento O (log n) (come coda basata su heap) ma ottenere l'elemento superiore dovrebbe essere O (1) [compresa la sua rimozione]. Potrebbero essere implementati anche usando l'algoritmo lock-free.

+0

Gli heap sono migliori degli elenchi di salto se li si utilizza correttamente. Usa un min-heap di elementi x, quando ti serve la x in alto. Non è necessario costruire un albero/heap di tutto il n. Solo x. –

+0

Scusa - colpa mia ho letto male il testo (ho capito che vuole un rapido sondaggio anche a costo di slow add). –

1

Il JDK ha una classe pqueue built-in (java.util.PriorityQueue) che si basa su un algoritmo heap.

Mi dispiace, ho appena visto il po 'di cumuli non si adattano alle vostre esigenze. Puoi spiegare perché? Puoi scrivere un comparatore personalizzato (o rendere i tuoi articoli comparabili) e PriorityQueue ordinerà i tuoi articoli in modo appropriato.

+0

Per quanto ho capito, trova getNext in O (log n) non accettabile. –

+1

Il problema sembra essere che ladi vuole essere in grado di ottenere i primi x elementi senza rimuoverli. Di solito non è un'operazione supportata da liste di priorità. –

+0

Mi piacerebbe votare alcuni oggetti e ottenere solo gli articoli migliori in termini di punteggio. Quindi stavo vagando se ci sono delle strutture dati che contengono solo gli elementi con il punteggio più alto ma offrono un'interfaccia elenco. Ciò significa che potrei passare in rassegna l'elenco degli articoli con il punteggio più alto in sequenza. Potrei ovviamente usare una coda di priorità basata su un algoritmo di heap che ha O (log n) inserimento e O (n) retrival, ottenere gli elementi di punteggio più alti e aggiungerli a un elenco. Ero solo curioso di sapere se esiste qualcosa di meglio. – ladi

4

se avete bisogno solo le k migliori articoli e si mai bisogno di guardare agli altri, è possibile utilizzare una semplice lista collegata o un array memorizzare solo l'attuale top k articoli, più un numero (il punteggio peggiore degli elementi nell'elenco).

Nell'operazione Add() è sufficiente confrontare l'elemento con il valore peggiore nell'elenco e, se possibile, scambiare l'attuale peggiore con l'elemento aggiunto. Questo richiede O (k) tempo nel caso peggioreper l'inserimento in quanto è necessario trovare l'elemento che ha attualmente il punteggio peggiore. Il caso medio, tuttavia, è O (1), poiché, quando si aggiungono elementi migliori all'elenco, la probabilità di dover eseguire uno swap tende a 0 (ovvero, in realtà non si aggiungono oggetti) .

Quindi, se si generano elementi a caso, le prestazioni è probabile che sia molto buono. Anche se generi articoli ordinati (caso peggiore), potrebbe essere abbastanza veloce per il tuo valore di k.

+0

bella idea ...... –

+1

Invece di una lista, se si utilizza min-heap (vedere la mia risposta), il caso peggiore è O (logK). Il resto è simile. In effetti l'utilizzo di min-heap come è piuttosto un metodo standard per questo problema! (Quando x è piccolo rispetto a n). –