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