Implementazione più efficiente di un albero in C ++

4

Ho bisogno di scrivere un albero in cui ogni elemento possa avere un numero qualsiasi di elementi figli, e per questo motivo ogni ramo dell'albero può avere qualsiasi lunghezza.

All'inizio l'albero riceverà solo elementi e quindi verrà utilizzato esclusivamente per l'iterazione, anche se si tratta di rami senza un ordine specifico.

L'albero avrà diversi milioni di elementi e deve essere veloce ma anche efficiente in termini di memoria.

Il mio piano rende una classe nodo per memorizzare gli elementi e i puntatori ai suoi figli. Quando l'albero è completamente costruito, lo trasformerebbe in un array o qualcosa di più veloce e, se possibile, caricato nella cache del processore.

La costruzione e la ricerca sull'albero sono due problemi diversi. Posso concentrarmi su come risolvere ogni problema sul modo migliore individualmente? La costruzione di deve essere il più veloce possibile ma può utilizzare la memoria a piacimento. Quindi la trasformazione in un formato che ci dà velocità durante l'iterazione dei rami dell'albero. Questo dovrebbe preferibilmente essere un array per evitare di andare avanti e indietro dalla RAM alla cache in ogni elemento della struttura.

Quindi la vera domanda è quale sia la struttura per implementare un albero per massimizzare la velocità di inserimento, come posso trasformarlo in una struttura che mi dà la migliore velocità e memoria?

    
posta Topo 28.09.2012 - 01:11
fonte

1 risposta

6

Un modo naturale per implementare un albero aggiornabile con numeri arbitrari di bambini per nodo è di reinterpretare un albero binario in modo tale che il collegamento "mano sinistra" punti al primo figlio del nodo e il collegamento "mano destra" punti al successivo figlio dello stesso genitore. Questo richiede due collegamenti per nodo e richiede l'attraversamento lineare degli elenchi per individuare un particolare bambino. Tuttavia, se l'ordine dei bambini non ha importanza, puoi semplicemente inserire ciascun bambino all'inizio dell'elenco dei bambini.

È possibile costruire un albero di sola lettura con un solo collegamento per nodo, concatenando tutti i figli di un dato nodo in un sub-vettore e rilasciando il collegamento della mano destra a favore dell'iterazione. Dovrai includere un flag booleano last_child o un campo child_count come parte della struttura del nodo di sola lettura; nota che la versione child_count consentirà l'accesso casuale agli elenchi secondari.

Se le query di sola lettura eseguono frequentemente iterate su lunghi elenchi di figli, ciò può migliorare notevolmente l'utilizzo della cache. In alternativa, se le query di sola lettura eseguono frequentemente iterazioni in modo approfondito, può essere più efficiente rilasciare il collegamento a sinistra a favore dell'iterazione, concatenando tutte le catene first-child in un sub-vettore.

In entrambi i casi, è possibile utilizzare uno STL vector<> per eseguire la gestione della memoria per l'albero di sola lettura, eseguendo un attraversamento (nell'ordine appropriato) dell'albero aggiornabile e utilizzando push_back() per aggiungere la versione di sola lettura di ogni nodo dell'albero, nell'ordine. Ricorda che dovrai utilizzare gli indici piuttosto che i puntatori per i tuoi link, poiché la spinta di un elemento potrebbe riallocare il vector<> .

Infine, ridurre al minimo le dimensioni della struttura del nodo di sola lettura può migliorare le prestazioni. Se il tuo nodo di sola lettura include un collegamento alla struttura dati originale, puoi eliminare in modo proficuo tutti i dati non necessari durante l'attraversamento di una query ma solo quando la query trova la destinazione. (Vieni a pensarci bene, l'albero aggiornabile potrebbe anche trarre vantaggio da questo.)

    
risposta data 28.09.2012 - 01:53
fonte

Leggi altre domande sui tag