Il tipo astratto di dati Albero
Tipo di dati e operazioni
Come l'ADT lista, anche l'ADT albero usa la nozione di posizione (position) per
memorizzare i suoi elementi
Anche qui un oggetto Position offre il seguente metodo:
element(): restituisce l'oggetto memorizzato in questa posizione
Strutture Dati
Il tipo astratto di dati Albero
Tipo di dati e operazioni
Metodi generici
size(): restituisce il numero dei nodi dell'albero
isEmpty(): verifica se l'albero è vuoto
iterator(): restituisce un iteratore degli elementi nei nodi dell'albero
positions(): restituisce un iteratore dei nodi dell'albero
Metodi di accesso
root(): restituisce la radice dell'albero; si verifica un errore se l'albero è vuoto
parent(v): restituisce il padre di v; si verifica un errore se v è la radice
children(v): restituisce un iteratore delle posizioni dei figli di v
Strutture Dati
Il tipo astratto di dati Albero
Tipo di dati e operazioni
Metodi di interrogazione:
isInternal(v): verifica se v è un nodo interno
isExternal(v): verifica se v è una foglia
isRoot(v): verifica se v è la radice
Metodi di modifica:
replace(v, e): rimpiazza con e l'elemento nel nodo v e restituisce il vecchio elemento
addRoot(e): aggiunge la radice (che conterrà l'elemento e) ad un albero vuoto
insertChild(v,e): aggiunge un nuovo figlio al nodo v (il nuovo figlio conterrà l'elemento e)
...
Strutture Dati
Il tipo astratto di dati Albero
Eccezioni
InvalidPositionException
ogni metodo che prende in input una posizione, lancia una InvalidPositionException
se questa posizione è invalida;
BoundaryViolationException
parent(v) lancia una BoundaryViolationException se il nodo v è la radice dell'albero;
EmptyTreeException
root() lancia una EmptyTreeException se invocato su un albero vuoto.
NonEmptyTreeException
addRoot(e) lancia una NonEmptyTreeException se invocato su un albero non vuoto.
Strutture Dati
Il tipo astratto di dati Albero
Interfaccia
public interface Tree<E> {
public int size();
public boolean isEmpty();
/** Restituisce un iteratore degli elementi memorizzati nell'albero. */
public Iterator<E> iterator();
/** Restituisce una collezione iterabile dei nodi. */
public Iterable<Position<E>> positions();
/** Rimpiazza l'elemento memorizzato in un dato nodo. */
public E replace(Position<E> v, E e)
throws InvalidPositionException;
/** Restituisce la radice dell'albero. */
public Position<E> root() throws EmptyTreeException;
/** Restituisce il padre di un dato nodo. */
public Position<E> parent(Position<E> v)
throws InvalidPositionException, BoundaryViolationException;
/** Restituisce una collezione iterabile dei figli di un dato nodo. */
public Iterable<Position<E>> children(Position<E> v)
throws InvalidPositionException;
...
}
Strutture Dati
Il tipo astratto di dati Albero
Interfaccia
public interface Tree<E> {
...
/** Ci dice se un dato nodo e` interno. */
public boolean isInternal(Position<E> v)
throws InvalidPositionException;
/** Ci dice se un dato nodo e` esterno (una foglia). */
public boolean isExternal(Position<E> v)
throws InvalidPositionException;
/** Ci dice se un dato nodo e` la radice di questo albero. */
public boolean isRoot(Position<E> v)
throws InvalidPositionException;
}
Strutture Dati
Il tipo astratto di dati Albero
Implementazione mediante struttura “linkata”
oggetto TreePosition<E>
parent
element
collezione dei figli
(può essere una lista o un array)
Strutture Dati
Il tipo astratto di dati Albero
Implementazione mediante struttura “linkata”
public interface TreePosition<E> extends Position<E>{
public void setElement(E o);
public PositionList<Position<E>> getChildren();
public void setChildren(PositionList<Position<E>> c);
public TreePosition<E> getParent();
public void setParent(TreePosition<E> v);
}
Strutture Dati
Il tipo astratto di dati Albero
Implementazione mediante struttura “linkata”
public class TreeNode<E> implements TreePosition<E>{
private E element; // l'elemento memorizzato in questo nodo
private TreePosition<E> parent; // nodo padre
private PositionList<Position<E>> children; // nodi figli
/** Costruttore */
public TreeNode(E element, TreePosition<E> parent,
PositionList<Position<E>> children) {
setElement(element);
setParent(parent);
setChildren(children);
}
...
}
Strutture Dati
Il tipo astratto di dati Albero
Implementazione mediante struttura “linkata”
public class TreeNode<E> implements TreePosition<E>{
...
/** Restituisce l'elemento in questa posizione */
public E element() { return element; }
public void setElement(E elem) { element=elem; }
public PositionList<Position<E>> getChildren() { return children; }
public void setChildren(PositionList<Position<E>> c) { children=c; }
public TreePosition<E> getParent() { return parent; }
public void setParent(TreePosition<E> v) { parent=v; }
}
Strutture Dati
Il tipo astratto di dati Albero
Implementazione mediante struttura “linkata”
public class LinkedTree<E> implements Tree<E>{
protected TreePosition<E> root; // riferimento al nodo radice
protected int size;
// numero di nodi
/** Crea un albero vuoto. */
public LinkedTree() {
root = null;
size = 0;
}
/** Se v e` un nodo valido, fa il cast a TreePosition, altrimenti lancia
** una eccezione. */
protected TreePosition<E> checkPosition(Position<E> v)
throws InvalidPositionException {
if (v == null || !(v instanceof TreePosition))
throw new InvalidPositionException("La posizione e` invalida");
return (TreePosition<E>) v;
}
...
}
Strutture Dati
Il tipo astratto di dati Albero
Implementazione mediante struttura “linkata”
public class LinkedTree<E> implements Tree<E>{
...
/** Ci dice se un nodo e` interno. */
public boolean isInternal(Position<E> v) throws InvalidPositionException {
return !isExternal(v);
}
/** Ci dice se un nodo e` esterno (una foglia). */
public boolean isExternal(Position<E> v) throws InvalidPositionException {
TreePosition<E> vv = checkPosition(v);
return (vv.getChildren() == null) || vv.getChildren().isEmpty();
}
/** Ci dice se un nodo e` il nodo radice*/
public boolean isRoot(Position<E> v) throws InvalidPositionException {
checkPosition(v);
return (v == root());
}
...
}
Strutture Dati
Il tipo astratto di dati Albero
Implementazione mediante struttura “linkata”
public class LinkedTree<E> implements Tree<E>{
...
/** Restituisce la radice di questo albero. */
public Position<E> root() throws EmptyTreeException {
if (root == null)
throw new EmptyTreeException("L'albero e` vuoto");
return root;
}
/** Restituisce una collezione iterable dei figli di un nodo. */
public Iterable<Position<E>> children(Position<E> v)
throws InvalidPositionException {
TreePosition<E> vv = checkPosition(v);
if (isExternal(v))
throw new InvalidPositionException("Una foglia non ha figli.");
return vv.getChildren();
}
...
}
Strutture Dati
Il tipo astratto di dati Albero
Implementazione mediante struttura “linkata”
public class LinkedTree<E> implements Tree<E>{
...
protected void preorderPositions(Position<E> v,PositionList<Position<E>> pos)
throws InvalidPositionException {
checkPosition(v);
pos.addLast(v);
if (isInternal(v))
for (Position<E> w : children(v))
preorderPositions(w, pos);
// ricorsione su ciascun figlio
}
...
}
Strutture Dati
Il tipo astratto di dati Albero
Implementazione mediante struttura “linkata”
public class LinkedTree<E> implements Tree<E>{
...
/** Restituisce una collezione iterable dei nodi dell'albero. */
public Iterable<Position<E>> positions() {
PositionList<Position<E>> positions = new NodePositionList<Position<E>>();
if(size != 0)
preorderPositions(root(), positions); //assegna le posizioni in preorder
return positions;
}
/** Restituisce un iteratore degli elementi memorizzati nei nodi */
public Iterator<E> iterator() {
Iterable<Position<E>> positions = positions();
PositionList<E> elements = new NodePositionList<E>();
for (Position<E> pos: positions)
elements.addLast(pos.element());
return elements.iterator(); // Un iteratore degli elementi
}
...
}
Strutture Dati
Il tipo astratto di dati Albero
Implementazione mediante struttura “linkata”
public class LinkedTree<E> implements Tree<E>{
...
/** Adds a root node to an empty tree */
public Position<E> addRoot(E e) throws NonEmptyTreeException {
if(!isEmpty())
throw new NonEmptyTreeException("Tree already has a root");
size = 1;
root = new TreeNode<E>(e,null,null);
return root;
}
...
}
Strutture Dati
Il tipo astratto di dati Albero
Implementazione mediante struttura “linkata”
public class LinkedTree<E> implements Tree<E>{
...
public Position<E> insertChild(Position<E> v, E e) throws
InvalidPositionException {
TreePosition<E> vv = checkPosition(v);
TreePosition<E> ww = new TreeNode<E>(e,vv,null);
PositionList<Position<E>> children = vv.getChildren();;
if(children == null){
children = new NodePositionList<Position<E>>();
vv.setChildren(children);
}
children.addLast(ww);
size++;
return ww;
}
...
}
Strutture Dati
Albero di test
public static void main(String[] args) {
LinkedTree<String> T = new LinkedTree<String>();
Position<String> r = T.addRoot("r");
Position<String> a = T.insertChild(r, "a");
Position<String> b = T.insertChild(r, "b");
T.insertChild(a, "c");
T.insertChild(b,"e");
T.insertChild(b,"f");
Position<String> g = T.insertChild(b,"g");
T.insertChild(g,"h");
T.insertChild(g,"i");
}
Strutture Dati