Un intero trattato potrebbe essere scritto su questo argomento; Tratterò solo alcuni punti salienti e terrò al minimo la discussione su altre strutture di dati (in effetti ci sono molte varianti). In tutta questa risposta, è il numero di chiavi nel dizionario.n
La risposta breve è che le tabelle hash sono più veloci nella maggior parte dei casi , ma possono essere molto peggiori. Gli alberi di ricerca hanno molti vantaggi, tra cui il comportamento nel caso peggiore , ma in alcuni casi sono più lenti.
Gli alberi di ricerca binaria bilanciata hanno una complessità abbastanza uniforme: ogni elemento prende un nodo nell'albero (in genere 4 parole di memoria) e le operazioni di base (ricerca, inserimento, cancellazione) impiegano il tempo (asintotico garantito) limite superiore). Più precisamente, un accesso nell'albero dura circa l o g 2 ( n ) confronti.O ( l g ( n ) )l o g2( n )
Le tabelle hash sono leggermente più variabili. Richiedono un array di circa puntatori. L'accesso a un elemento dipende dalla qualità della funzione hash. Lo scopo di una funzione hash è di disperdere gli elementi. Una tabella hash "funziona" se tutti gli elementi che si desidera archiviare hanno hash diversi. In questo caso, le operazioni di base (ricerca, inserimento, eliminazione) richiedono O ( 1 ) tempo, con una costante abbastanza piccola (un calcolo dell'hash più una ricerca del puntatore). Questo rende le tabelle hash molto veloci in molti casi tipici.2 nO ( 1 )
Un problema generale con le tabelle hash è che la complessità non è garantita.O ( 1 )
- Inoltre, c'è un punto in cui la tabella diventa piena; quando ciò accade (o meglio, poco prima che accada), la tabella deve essere ingrandita, il che richiede di spostare tutti i suoi elementi, per un costo . Questo può introdurre un comportamento "a scatti" quando vengono aggiunti molti elementi.O ( n )
- O ( 1 )
Quando si inserisce la localizzazione dei dati nel mix, le tabelle di hash funzionano male. Funzionano proprio perché memorizzano elementi correlati distanti, il che significa che se l'applicazione cerca elementi che condividono un prefisso in sequenza, non trarrà beneficio dagli effetti cache. Ciò non è rilevante se l'applicazione effettua ricerche essenzialmente casuali.
Un altro fattore a favore degli alberi di ricerca è che sono una struttura di dati immutabile : se devi prendere una copia di un albero e modificarne alcuni elementi, puoi condividere la maggior parte della struttura di dati. Se si prende una copia di una tabella hash, è necessario copiare l'intero array di puntatori. Inoltre, se lavori in linguaggi puramente funzionali, le tabelle hash spesso non sono un'opzione.
K1≡ k2⟹h ( k1) = h ( k2)
In particolare, se hai bisogno dell'ordine delle chiavi, ad esempio se vuoi essere in grado di elencare le chiavi in ordine alfabetico, le tabelle hash non sono di aiuto (dovrai ordinarle), mentre tu può attraversare direttamente un albero di ricerca in ordine.
È possibile combinare alberi di ricerca binari e tabelle hash sotto forma di alberi hash . Un albero hash memorizza le chiavi in un albero di ricerca in base al loro hash. Ciò è utile, ad esempio, in un linguaggio di programmazione puramente funzionale in cui si desidera lavorare su dati che non hanno una relazione d'ordine facile da calcolare.
Quando le chiavi sono stringhe (o numeri interi), un trie può essere un'altra opzione. Un trie è un albero, ma indicizzato in modo diverso da un albero di ricerca: scrivi la chiave in binario e vai a sinistra per uno 0 e a destra per uno 1. Il costo di un accesso è quindi proporzionale alla lunghezza della chiave. I tentativi possono essere compressi per rimuovere nodi intermedi; questo è noto come patricia trie o radix tree . Gli alberi Radix possono sovraperformare gli alberi bilanciati, in particolare quando molte chiavi condividono un prefisso comune.