2011-12-29 6 views
5

Ho un PriorityQueue contenente riferimenti ad alcuni oggetti. Quando inizialmente inserisco gli elementi nella coda di priorità, l'ordine viene mantenuto dalla struttura dei dati. Ora dopo un'operazione di rimozione aggiorno alcuni dei riferimenti che sono trattenuti dalla coda di priorità. Idealmente ciò richiede un'operazione di reheapify sulla coda di priorità, ma come è ovvio visto che sto modificando i riferimenti selezionati esternamente, non è possibile attivare una reheapify. Quindi qual è il modo migliore per assicurarmi di essere in grado di trarre il massimo vantaggio da un heap come fast extract max in presenza di modifiche a elementi arbitrari all'interno della coda? Vedo che ho bisogno di una struttura dati migliore?Reheapify java.util.PriorityQueue dopo l'aggiornamento degli elementi

Per essere più specifici ho bisogno di un'implementazione di qualcosa come un heap di Fibonacci in Java. http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm È disponibile?

+0

Ho un'implementazione di un heap di Fibonacci in Java se sei interessato. È disponibile online all'indirizzo http://www.keithschwarz.com/interesting/code/?dir=fibonacci-heap. Spero che sia d'aiuto! – templatetypedef

+0

Anche gli heap di fibonacci non sono resistenti alla luce delle modifiche fuori banda ai pesi degli elementi. Penso che sia necessario rimuovere un elemento prima di modificarlo e reinserirlo in seguito. –

+0

rimuovere un elemento arbitrario dall'heap richiederà la costruzione di heap O (n), suppongo. –

risposta

2

È possibile utilizzare il proprio albero che consente elementi duplicati anziché heap. Più facile però, è possibile utilizzare TreeMap<PriorityKey, LinkedHashSet<Value>>. Tutte le operazioni sono O (log priorityType):

  • aggiunta è get(priority).add(value), se ottenere rendimenti nulli, put(priority, new LinkedHashSet())
  • rimozione di un elemento arbitrario è simile, tranne che deve eliminare la priorità fuori dalla mappa se il set è vuoto.
  • poll() è

-

Entry<PriorityKey, LinkedHashSet<Value>> e = map.firstEntry(); 
if (e==null) return null; 
Iterator<Value> i = e.getValue().iterator(); 
Value v = i.next(); //must always have at least one element. 
i.remove(); 
if (!i.hasNext()) map.remove(e.getKey()); 
return v; 

Ancora se è necessario modificare la priorità è necessario rimuovere e aggiungere l'elemento.

+0

OK ... quindi direi che PriorityQueue in Java non implementa l'operazione DecreaseKey né fornisce un modo per l'utente di implementarlo in modo efficiente. –

+0

@iamrohitbanga, trovare una chiave nell'heap è O (n), quindi è possibile rimuovere/aggiungere che è (log N), ancora una volta se è necessario accedere a un elemento casuale nella coda si starebbe meglio con un albero . – bestsss

1

Forse una NavigableMap si adatta alle tue esigenze: facile identificazione dell'elemento "più alto" o "più basso", inserimento veloce e tempo di accesso, e puoi aggiornare facilmente i valori.

http://docs.oracle.com/javase/7/docs/api/java/util/NavigableMap.html

TreeMap implementa NavigableMap, e quindi fornisce i/lastEntry metodi firstEntry, e molti altri.

+0

non puoi avere elementi duplicati nella mappa e deve essere ordinato per priorità. la soluzione per l'utilizzo di un albero (mappa) implica la mappatura della priorità-> raccolta.(cosa ho postato) – bestsss