![]() ![]() |
|
La classe TreeSet
fornisce una realizzazione dell'interfaccia Set utilizzando
gli alberi binari di ricerca. Gli elementi di un insieme vengono memorizzati
come valori delle chiavi dei nodi dell'albero. Poiché su questi
elementi deve essere definito un ordinamento totale, richiederemo che siano
di tipo Comparable, e useremo il metodo compareTo
per confrontare gli elementi.
La classe TreeSet ha due variabili d'istanza:
|
![]() ![]() |
|
Per la ricerca di un elemento in un albero binario
di ricerca vediamo il primo esempio di algoritmo che sfrutta la proprietà
(ABR).
Questa proprietà permette di ridurre la ricorsione doppia, tipica
degli algoritmi su alberi binari, ad una ricorsione singola.
L'algoritmo è il seguente:
|
![]() ![]() |
|
Questo permette anche di sostituire la ricorsione
con una semplice iterazione (while).
Il metodo ausiliario containsHelper usa
in realtà un ciclo while (invece della ricorsione)
per cercare un nodo contenente l'oggetto
x passato per
parametro. Restituisce questo nodo se esiste,
null altrimenti.
|
![]() ![]() |
|
Per inserire un elemento in un albero binario
di ricerca si sfrutta ancora la proprietà (ABR).
Confrontiamo il valore dell'elemento x da inserire con quello contenuto
nella radice dell'albero:
|
![]() ![]() |
|
Il metodo ausiliario addHelper
inserisce un oggetto
x in un albero non vuoto t,
restituendo true se x non appartiene già
all'albero e false altrimenti.
Il metodo add (che realizza il corrispondente metodo di Set) inserisce direttamente l'elemento se l'albero è vuoto ed invoca addHelper se l'albero non è vuoto.
|
![]() ![]() |
|
I metodi min, max,
successor
e predecessor sono pubblici, quindi sono offerti da TreeSet
in aggiunta ai metodi dell'interfaccia
Set.
Se l'albero non è vuoto, il metodo min determina il nodo contenente la chiave più piccola dell'albero partendo dalla radice e passando da un nodo al suo figlio sinistro, fin quando non raggiunge un nodo senza figlio sinistro. La proprietà (ABR) garantisce che il nodo così individuato sia il minimo. Il metodo max è realizzato in modo
simmetrico.
|
![]() ![]() |
|
Il metodo successor restituisce
il nodo contenente la chiave immediatamente successiva nell'ordinamento
alla chiave del nodo t passato per argomento
(null se t
contiene il massimo).
La proprietà (ABR) permette di realizzare successor senza confrontare esplicitamente le chiavi contenute dell'albero. Si distinguono tre casi:
|
![]() ![]() |
|
Cancellazione di un elemento x da un albero di ricerca.Il metodo remove individua il nodo z che contiene l'oggetto x da cancellare, invocando il metodo containsHelper già visto. Se esiste tale nodo, remove invoca il metodo ausiliario removeHelper, che elimina z dall'albero.
|
![]() ![]() |
|
Per la cancellazione del nodo z
dall'albero distinguiamo tre casi:
Il metodo removeHelper riportato di seguito
tratta i tre casi appena descritti in modo leggermente diverso. In sintesi,
nel codice sotto, prima si individuano il nodo da cancellare (z
stesso se ha meno di due figli, il suo successore altrimenti) e l'eventuale
figlio del nodo da cancellare, e quindi si elimina il nodo, sfruttando
il fatto che ha un solo figlio.
|
![]() ![]() |
|
Il metodo iterator della classe
di TreeSet restituisce un iteratore che permette di visitare
i nodi dell'albero binario di ricerca associato secondo l'ordine simmetrico,
e quindi in ordine crescente.
La classe interna ProtectedItr che realizza l'iteratore per TreeSet è molto simile alla sua omonima interna alla classe LinkedList. Le differenze sono:
|
![]() ![]() |
|
Qual'è il costo delle operazioni sugli
alberi binari di ricerca realizzate nella classe TreeSet?
![]() ![]() Diverso è il caso pessimo: l'altezza di un albero
binario di ricerca varia a seconda di come gli elementi sono inseriti o
cancellati.
Esistono molte estensioni degli alberi binari di ricerca,
come gli alberi RB descritti in [CLR], gli alberi AVL e i 2-3 alberi, che
mantengono costantemente la struttura dell'albero "quasi perfettamente
bilanciata", garantendo un costo di |
![]() ![]() |
|
1) Realizzare il metodo
2) Realizzare il metodo
3) Realizzare il metodo
4) Realizzare il metodo
5) Realizzare il metodo
6) Realizzare il metodo
|
![]() ![]() |
|
![]() ![]() |
1) Estendere la classe TreeSet
con il metodo toArray( ) che restituisce un array contenente
tutti gli oggetti contenuti nell'albero ordinati in ordine crescente.
2) L'elemento ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]()
3) Estendere la classe TreeSet aggiungendo
il metodo
|