Alberi binari Gli alberi binari rappresentano una delle strutture dati dinamiche più importanti dell'informatica. Un albero binario consiste di componenti ripetuti (nodi) arrangiati secondo una struttura ad albero (invertito). L'elemento in cima all'albero è chiamato radice (root). Gli elementi situati immediatamente al di sotto di un nodo ne sono chiamati figli (children), di rimando, l'elemento situato direttamente al di sopra di un altro nodo ne è detto il genitore (parent). Infine, un elemento privo di figli è chiamato foglia (leaf) dell'albero. In generale, un albero binario rappresenta una struttura dati contenente una sequenza di elementi registrati secondo l'ordine di inserimento ma riordinati secondo un assegnato criterio di ordinamento. Tale ordinamento viene espresso a mezzo di una coppia di puntatori detti puntatore sinistro e puntatore destro (o anche puntatore precedente e puntatore successivo). L'elemento puntato dal puntatore sinistro precede, secondo la relazione di ordinamento applicata, l'elemento in esame, viceversa l'elemento puntato dal puntatore destro segue l'elemento in esame. Se ne deduce che un nodo debba rappresentare una struttura composta dal dato (o dai dati) da gestire e da una coppia di puntatori a oggetti dello stesso tipo. In un albero binario così definito, ciascun elemento è maggiore (inteso sempre secondo il criterio di ordinamento prescelto) di tutti gli elementi appartenenti al sotto-albero ''inferiore'' (o ''sinistro'') e minore di quelli appartenenti al sotto-albero ''superiore'' (o ''destro''). Da tali proprietà discendono in modo naturale gli algoritmi di ricerca, inserimento e prelievo degli elementi dell'albero. Ciò rende particolarmente efficiente le operazioni di ricerca attraverso le visite dell'albero e le operazioni di ordinamento. Naturalmente su una struttura ad albero sarà possibile definire procedure elementari di inizializzazione dell'albero, inserimento di un nodo, estrazione di un nodo, stampa dell'elenco completo. Inoltre sarà necessario prevedere la definizione di predicati logici atti a verificare se l'albero è vuoto (ossia da se è da inizializzare) e se un dato elemento è o meno presente nell'albero. Quando viene letto il primo valore viene allocata una variabile (il root node) atta ad ospitarlo e i due puntatori componenti vengono annullati. Quando viene letto il valore successivo, viene creato un nuovo nodo per poterlo ospitare. Se il nuovo valore risulta minore del valore del nodo radice, il puntatore sinistro di root è indirizzato a questo nuovo nodo. Se, invece, il nuovo valore risulta maggiore del valore del nodo radice, è il puntatore destro di root ad essere indirizzato a questo nuovo nodo. Letto un nuovo valore ed allocato memoria per esso, se esso risulta maggiore del valore di root ma il puntatore destro è già associato, allora esso viene confrontato con il valore puntato da destro ed il nuovo nodo viene inserito nella posizione appropriata al di sotto di quel nodo. Se, invece, il nuovo valore risulta minore del valore di root ma il puntatore sinistro è già associato, allora esso viene confrontato con il valore puntato da sinistro ed il nuovo nodo viene inserito nella posizione appropriata al di sopra di quel nodo. Un albero binario consente, dunque, di ordinare i dati all'interno di una struttura indipendentemente dall'ordine in cui vengono inseriti e senza operare alcuna permutazione degli elementi inseriti. Il vantaggio di usare una struttura ad albero cresce enormemente al crescere del numero di elementi. Infatti un albero perfettamente bilanciato consente di eseguire le operazioni di ricerca con un numero di visite pari a log2 n essendo n il numero di elementi dell'albero. Si supponga, ad esempio, di dover inserire all'interno di un database 65535 valori. Nel caso in cui si debba ricercare un valore all'interno di questo elenco, utilizzando una lista concatenata il numero medio di valori da processare sarebbe pari a 65535/2=32768. Inserendo, invece, tali valori all'interno di una struttura ad albero, tutti i valori possono essere agevolmente inseriti in appena 16 ''livelli'' così che il numero massimo di valori da processare prima di trovare il valore desiderato è appena 16. Questo semplice esempio fa comprendere l'enorme efficienza associata alle procedure di gestione dati attraverso strutture binarie. Per tale ragione molti database sono strutturati come alberi binari. E' da precisare, tuttavia, che non sempre una struttura ad albero è così efficiente. Poiché, infatti, l'inserimento dei nodi nell'albero dipende dall'ordine in cui i dati vengono letti può accadere che una parte di albero appaia molto più ''nutrita'' di un altra e l'albero sia fortemente sbilanciato, ciò aumentando il numero di livelli da processare nella visita all'albero durante le operazioni di ricerca. In particolare la struttura può degenerare in una lista lineare qualora gli elementi vengano inseriti proprio secondo l'ordinamento prescelto. In quest'ultimo caso si perderà del tutto il vantaggio di lavorare con una struttura binaria.