Ma ciò comporta la creazione di un nuovo set n volte. C'è un modo per farlo e creare solo un nuovo set una volta?
Per quanto ne so, no. Direi che hai un'implementazione perfetta, funziona in O (lg n) - e anche la sua concisa :) La maggior parte delle implementazioni di heap ti danno comunque O (lg n) per eliminare min, quindi quello che hai è circa come bene come puoi ottenerlo
Potrebbe essere possibile ottenere una velocità leggermente migliore ruotando l'albero bilanciato e implementando una funzione per rilasciare un ramo sinistro o destro per tutti i valori superiori a un determinato valore. Non credo che un albero AVL o un albero RB siano appropriati in questo contesto, dal momento che non puoi davvero mantenere i loro invarianti, ma un albero randomizzato ti darà i risultati che desideri.
Un treap funziona davvero bene per questo, perché utilizza la casualizzazione piuttosto che gli invarianti di albero per mantenersi relativamente bilanciato. A differenza di un albero AVL o di un albero RB, è possibile dividere un treap su un nodo senza preoccuparsi di essere sbilanciato.Ecco un'implementazione Treap ho scritto qualche mese fa:
http://pastebin.com/j0aV3DJQ
Ho aggiunto una funzione split
, che vi permette di prendere un albero e tornare due alberi che contengono tutti i valori inferiori e tutti i valori maggiori di un dato un valore. split
viene eseguito in O (lg n) utilizzando un unico passaggio attraverso l'albero, in modo da poter potare interi rami del vostro albero in un colpo solo - purché si conosca il valore da dividere su.
Ma se voglio rimuovere il n massimo elementi ... posso solo eseguire il sopra n volte, o c'è un modo più veloce per farlo?
Utilizzando la mia classe Treap
:
open Treap
let nthLargest n t = Seq.nth n (Treap.toSeqBack t)
let removeTopN n t =
let largest = nthLargest n t
let smallerValues, wasFound, largerValues = t.Split(largest)
smallerValues
let e = Treap.empty(fun (x : int) (y : int) -> x.CompareTo(y))
let t = [1 .. 100] |> Seq.fold (fun (acc : Treap<_>) x -> acc.Insert(x)) e
let t' = removeTopN 10 t
removeTopN
viene eseguito in tempo O (n + lg m), dove n è l'indice nella sequenza albero e m è il numero di elementi nella struttura.
non faccio garanzie circa l'accuratezza del mio codice, usare a vostro rischio e pericolo;)
Potresti descrivere esattamente i requisiti necessari dalla tua struttura di dati? Hai bisogno di una struttura dati simile ad un heap per un accesso rapido agli articoli min/max o hai bisogno anche di un rapido accesso casuale al tuo elenco? Hai bisogno di qualcosa di più esotico come un albero di intervallo per l'interrogazione di intervalli di elementi? – Juliet
Si tratta di un follow-up della mia domanda precedente http://stackoverflow.com/questions/3407772/f-immutable-variable-sized-window-data-structure Quindi ... in generale, ho solo bisogno di aggiungere cose su la parte anteriore e rimuovere le cose dalla parte posteriore. Sto chiedendo a questa domanda, perché se corro s.Remove (s.MaximumElement) 10 volte, si sta andando a creare 10 strutture di dati immutabili intermedie ... Sembra un'operazione "intelligente" potrebbe "cancellare" tutti i 10 ultimi nodi e restituire la nuova struttura. – mentics