11

Ho una collezione di articoli (grandi razionali) che elaborerò. In ogni caso, l'elaborazione consisterà nel rimuovere l'elemento più piccolo nella raccolta, fare del lavoro e aggiungere 0-2 nuovi elementi (che saranno sempre più grandi dell'elemento rimosso). La raccolta verrà inizializzata con un elemento e il lavoro continuerà fino a quando non sarà vuoto. Non sono sicuro delle dimensioni che la raccolta probabilmente raggiungerà, ma mi aspetterei negli articoli da 1M a 100M. Non avrò bisogno di localizzare oggetti diversi dal più piccolo.Un albero rosso-nero è la mia struttura dati ideale?

Attualmente sto pianificando di utilizzare un albero rosso-nero, possibilmente ottimizzato per mantenere un puntatore all'elemento più piccolo. Comunque non ne ho mai usato uno prima, e non sono sicuro che il mio schema di utilizzo si adatti bene alle sue caratteristiche.

1) Esiste il pericolo che lo schema di cancellazione da sinistra + inserimento casuale influenzi le prestazioni, ad esempio richiedendo un numero significativamente maggiore di rotazioni rispetto all'eliminazione casuale? O cancellerà e inserirà le operazioni ancora O (log n) con questo schema di utilizzo?

2) Qualche altra struttura di dati mi darà prestazioni migliori, sia a causa del modello di eliminazione o sfruttando il fatto che ho sempre bisogno di trovare l'elemento più piccolo?

Aggiornamento: felice che ho chiesto, l'heap binario è chiaramente una soluzione migliore per questo caso e, come promesso, si è rivelato essere molto facile da implementare.

Hugo

+0

A meno che non si sappia per certo che i nodi che dovrebbero essere cancellati logicamente non saranno necessari per i nuovi valori calcolati, si potrebbe desiderare di ignorare o ritardare le delezioni. Un approccio Halt & Sweep dovrebbe funzionare per quest'ultimo, dove le radici dei sub-alberi che sono diventati troppo disordinati sono visitati dal codice di riequilibrio per riequilibrare l'unità. Ciò impedisce la degenerazione lorda, pur offrendo la probabile prospettiva di prestazioni senza cancellazione. – RocketRoy

risposta

12

A binary heap è molto meglio per quello che vuoi. È più facile da implementare e più veloce poiché ti interessa solo individuare l'elemento e gli inserimenti più piccoli. Individuare l'elemento più piccolo è O (1), rimuoverlo è O (log N), e un inserimento è anche O (log N).

+0

in realtà, se sa che inserisce sempre un oggetto più grande di quello rimosso, un heap binario (treap) finirà per essere molto sbilanciato in un punto. 100M records è molto, quindi questo può diventare abbastanza sbilanciato così che non è più O (log (n)), ma piuttosto O (n) - per esempio, se l'altezza del treap termina con 160k quando n = 100M, allora è O (n/((lgn)^2)) – Etai

+0

@Etai - un heap binario è sempre 'O (log N)' per le operazioni che ho menzionato. Non so perché hai menzionato traci, la mia risposta si riferisce a cumuli binari, non trucchi. Gli heap svolgono effettivamente un ruolo nella struttura dei treap, ma i due sono strutture di dati differenti. – IVlad

+0

L'inserimento dell'heap binario è in media 'O (1)' (caso peggiore per Brodal), e questa è la ragione principale per usarlo su BST: http://stackoverflow.com/a/29548834/895245 –

5

Un mucchio vi darà O (1) O (log n) la rimozione e O (log n) l'inserimento, ed è molto più facile da implementare rispetto a un albero rosso-nero

+3

In realtà, la rimozione è O (log N), ** localizzazione (ricerca del valore di) ** il minimo/massimo è O (1). – IVlad

+0

Non ho mai visto un heap con elementi 1M-100M, qualcuno ha qualche informazione su come questo influisce sulla sua velocità? –

+3

@NickLarsen: questo è esattamente ciò a cui serve la notazione Big-O. –

1

È utile sapere come creare strutture di dati più complesse, se necessario. Tuttavia, in genere la soluzione migliore è iniziare il più semplice possibile e utilizzare solo qualcosa di più complesso quando risulta necessario.

L'unica volta in cui ho implementato un albero autobilanciato è stata una volta in cui mi è capitato di sapere che il mio albero sarebbe stato davvero grande (oltre 10.000 elementi), e che i dati sarebbero arrivati ​​a scatti ordinati. Ciò significava che se avessi usato un normale albero binario, avrei finito con quasi una lista collegata.

Se i dati vengono inseriti in un ordine casuale, non dovresti preoccuparti di un algoritmo di bilanciamento.

+0

Accetto in generale su KISS prima, e complesso solo se necessario. Ci sono molti modi per aggirare il requisito dell'auto-bilanciamento, come la creazione di un indice per leggere i dati in ordine casuale, ma l'avvertenza è che funziona solo se si conosce il requisito. IE: non per uso generico, come nella creazione di una libreria. Anche pessima etichetta per lasciare questo compito a qualche povero bastardo che deve mantenere il tuo codice in seguito. Detto questo, sono generalmente d'accordo con la tua filosofia. – RocketRoy

Problemi correlati