[Dynamic Tree] (
max 14 punti)
Si vuole definire una classe per gestire alberi dinamici con
valori di tipo parametrico
V
associati ai nodi. Gli alberi sono
dinamici nel senso
che i figli di un nodo sono generati "on demand", cioè, quando
sono richiesti per la prima volta. Un albero dinamico è costruito fornendo
la radice (un valore di tipo
V
) e un
generatore che è
un oggetto che implementa l'iterfaccia:
import java.util.Set;
public interface Generator<V> {
//Ritorna l'insieme (possibilmente vuoto) dei valori generati dal valore x
Set<V> generate(V x);
}
I figli di un nodo con valore
val
corrispondono ai valori ritornati
dal metodo
generate(val)
che non erano presenti nell'albero
al momento in cui i figli sono stati richiesti la prima volta.
Un nodo i cui figli sono stati già generati si dice
espanso.
Ad esempio, supponiamo che il tipo
V
è
String
e il generatore
per ogni stringa
x
genera l'insieme di tutte le parole italiane che
si ottengono da
x
sostituendo uno dei caratteri di
x
.
Se l'albero è creato con la radice
"giallo"
, dopo tre
espansioni potrebbe avere la seguente forma:
giallo 1 {piallo, gialli, gialle, gialla}
______________________________|______________________________
| | | |
piallo gialli gialle 2 {gialli, pialle, gialla, giallo} gialla
|
pialle 3 {piallo, gialle, pialla}
|
pialla
A destra di ogni nodo espanso è indicato (in grigio) il numero d'ordine dell'espansione
e l'insieme dei valori prodotti dal generatore. Chiaramente, la forma dell'albero
dipende da quali nodi sono stati espansi e dall'ordine in cui sono stati espansi.
Definire una classe
DTree
per gestire alberi dinamici con valori
di tipo parametrico
V
con i seguenti costruttori e metodi.
-
Un costruttore che prende in input un generatore e un valore e costruisce un albero
con la sola radice (con il valore di input). Se il generatore o il valore è
null
,
lancia NullPointerException
.
-
Un metodo che prende un valore e ritorna
true
se il valore è un
nodo dell'albero che è stato espanso, altrimenti ritorna false
.
-
Un metodo
Set<V> children(V val)
che ritorna, in un insieme
creato ex novo, i figli del nodo con valore val
. Se
il nodo non è stato ancora espanso, genera i figli usando il generatore
tenendo conto dei nodi già presenti nell'albero. Se è espanso, ritorna
i figli che sono già stati generati.
-
Un metodo
List<V> path(V val)
che ritorna la lista dei valori
nel cammino dell'albero da val
alla radice.
-
Un metodo
int height(V val)
che ritorna la lunghezza del più
lungo cammino da val
a una foglia del suo
sottoalbero.
I tre metodi
children
,
path
e
height
,
se
val
non appartiene all'albero, lanciano
IllegalArgumentException
.
La classe deve implementare
Iterable
per iterare sui valori dell'albero
e l'iteratore non deve permettere la rimozione.