Implementazione Java di Alberi Binari A.A. 16/17 DA1 - Andrea Pietracaprina 1
Idea: struttura linkata Un nodo contiene Element Parent node Left child node Right child node B B A D A D C E C E A.A. 16/17 DA1 - Andrea Pietracaprina 2
Schema interfacce e classi Position<E> extends BTPosition<E> implements BTNode<E> usa Tree<E> usa extends BinaryTree<E> implements LinkedBinaryTree<E> PositionList<E> extends Iterable<E> implements NodePositionList<E> N.B. In [GTG14] implementazione alternativa A.A. 16/17 DA1 - Andrea Pietracaprina 3
Interfaccia BinaryTree public interface BinaryTree<E> extends Tree<E> { public Position<E> left(position<e> v); public Position<E> right(position<e> v); public Position<E> sibling(position<e> v); public boolean hasleft(position<e> v); public boolean hasright(position<e> v); N.B. Eredita i metodi dell interfaccia Tree<E> A.A. 16/17 DA1 - Andrea Pietracaprina 4
Interfaccia BTPosition public interface BTPosition<E> extends Position<E> { public void setelement(e o) ; public BTPosition<E> getleft() ; public void setleft(btposition<e> v) ; public BTPosition<E> getright() ; public void setright(btposition<e> v) ; public BTPosition<E> getparent() ; public void setparent(btposition<e> v) ; N.B. Eredita dall interfaccia Position<E> il metodo E element() A.A. 16/17 DA1 - Andrea Pietracaprina 5
Classe BTNode public class BTNode<E> implements BTPosition<E> { private E element; // element stored at this node private BTPosition<E> left, right, parent; // adjacent nodes public BTNode(E element, BTPosition<E> parent, BTPosition<E> left, BTPosition<E> right) { setelement(element); setparent(parent); setleft(left); setright(right); public E element() { return element; public void setelement(e o) { element=o; public BTPosition<E> getleft() { return left; public void setleft(btposition<e> v) { left=v; public BTPosition<E> getright() { return right; public void setright(btposition<e> v) { right=v; public BTPosition<E> getparent() { return parent; public void setparent(btposition<e> v) { parent=v; A.A. 16/17 DA1 - Andrea Pietracaprina 6
Classe LinkedBinaryTree public class LinkedBinaryTree<E> implements BinaryTree<E> { protected BTPosition<E> root; // reference to the root protected int size; // number of nodes /* Constructor */ public LinkedBinaryTree() { root = null; size = 0; protected BTPosition<E> createnode(e element, BTPosition<E> parent, BTPosition<E> left, BTPosition<E> right) { return new BTNode<E>(element,parent,left,right); public Position<E> addroot(e e) throws NonEmptyTreeException{ if (!isempty) throw new NonEmptyTreeException( Tree already has a root ); size = 1; root = createnode(e,null,null,null); return root; N.B.L uso di BTNode è confinato. al metodo createnode A.A. 16/17 DA1 - Andrea Pietracaprina 7
Classe LinkedBinaryTree protected BTPosition<E> checkposition(position<e> v) throws InvalidPositionException{ if (v == null!(v instanceof BTPosition)) throw new InvalidPositionException( Position is invalid"); return (BTPosition<E>) v; A.A. 16/17 DA1 - Andrea Pietracaprina 8
Classe LinkedBinaryTree public Position<E> root() throws EmptyTreeException{ if (root == null) throw new EmptyTreeException( Tree is empty"); return root; public boolean hasleft(position<e> v) throws InvalidPositionException{ BTPosition<E> vv = checkposition(v); return (vv.getleft()!=null);; public Position<E> left(position<e> v) throws InvalidPositionException, BoundaryViolationException { BTPosition<E> vv = checkposition(v); Position<E> leftpos = vv.getleft(); if (leftpos == null) throw new BoundaryViolationException( No left child"); return leftpos; A.A. 16/17 DA1 - Andrea Pietracaprina 9
Classe LinkedBinaryTree public Position<E> insertleft(position<e> v, E e) throws InvalidPositionException { BTPosition<E> vv = checkposition(v); Position<E> leftpos = vv.getleft(); if (leftpos!= null) throw new InvalidPositionException("Node already has a left child"); BTPosition<E> w = createnode(e, vv, null, null); vv.setleft(w); size++; return w; Oss. Questo metodo (e l analogo metodo insertright) permette di aggiungere all albero un nuovo nodo, contenete un dato elemento e, come figlio sinistro (risp., destro) di un dato nodo v. Il metodo remove nel prossimo lucido invece serve per eliminare un nodo che ha al più un figlio A.A. 16/17 DA1 - Andrea Pietracaprina 10
Classe LinkedBinaryTree public E remove(position<e> v) throws InvalidPositionException { BTPosition<E> vv = checkposition(v); BTPosition<E> leftpos = vv.getleft(); BTPosition<E> rightpos = vv.getright(); if (leftpos!= null && rightpos!= null) throw new InvalidPositionException("Cannot remove node"); BTPosition<E> ww; // the only child of v, if any if (leftpos!= null) ww = leftpos; else if (rightpos!= null) ww = rightpos; else ww = null; if (vv == root) { if (ww!= null) ww.setparent(null); root = ww; else { BTPosition<E> uu = vv.getparent(); if (vv == uu.getleft()) uu.setleft(ww); else uu.setright(ww); if(ww!= null) ww.setparent(uu); size--; return v.element(); N.B. Si restituisce l elemento contenuto nel nodo rimosso A.A. 16/17 DA1 - Andrea Pietracaprina 11
Classe LinkedBinaryTree protected void preorderpositions(position<e> v, PositionList<Position<E>> pos) throw InvalidPositionException { pos.addlast(v); // visit node v if (hasleft(v)) preorderpositions(left(v), pos); // recurse on left child if (hasright(v)) preorderpositions(right(v), pos); // recurse on right child public Iterable<Position<E>> positions() { PositionList<Position<E>> positions = new NodePositionList<Position<E>>(); if(size!= 0) preorderpositions(root(), positions); return positions; A.A. 16/17 DA1 - Andrea Pietracaprina 12
Classe LinkedBinaryTree public Iterable<Position<E>> children(position<e> v) throw InvalidPositionException { PositionList<Position<E>> children = new NodePositionList<Position<E>>(); if (hasleft(v)) children.addlast(left(v)); if (hasright(v)) children.addlast(right(v)); return children; 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(); N.B. In ogni iterazione del ciclo for nel metodo iterator(), alla variabile pos viene assegnato il prossimo oggetto dell iteratore fornito da positions.iterator(), ovvero la prossima position (vedi lucidi seguenti) A.A. 16/17 DA1 - Andrea Pietracaprina 13
Statement for-each for (Position<E> pos: positions) elements.addlast(pos.element()); equivale a for (Iterator<Position<E>> it = positions.iterator(); it.hasnext(); ) { Position<E> pos = it.next(); elements.addlast(pos.element()); A.A. 16/17 DA1 - Andrea Pietracaprina 14