package net.datastructures; import java.util.Iterator; import net.datastructures.*; //begin#fragment Tree /** * A linked class for a tree where nodes have an arbitrary number of children. //end#fragment Tree * @author Luca Vismara, Roberto Tamassia, Michael Goodrich, Eric Zamore //begin#fragment Tree */ public class LinkedTree implements Tree { protected TreePosition root; // reference to the root protected int size; // number of nodes /** Creates an empty tree. */ public LinkedTree() { root = null; // start with an empty tree size = 0; } /** Returns the number of nodes in the tree. */ public int size() { return size; } //end#fragment LinkedTree /** Returns whether the tree is empty. */ public boolean isEmpty() { return (size == 0); } //begin#fragment LinkedTree /** Returns whether a node is internal. */ public boolean isInternal(Position v) throws InvalidPositionException { return !isExternal(v); } //end#fragment LinkedTree /** Returns whether a node is external. */ public boolean isExternal(Position v) throws InvalidPositionException { TreePosition vv = checkPosition(v); // auxiliary method return (vv.getChildren() == null) || vv.getChildren().isEmpty(); } //begin#fragment LinkedTree /** Returns whether a node is the root. */ public boolean isRoot(Position v) throws InvalidPositionException { checkPosition(v); return (v == root()); } //begin#fragment LinkedTree /** Returns the root of the tree. */ public Position root() throws EmptyTreeException { if (root == null) throw new EmptyTreeException("The tree is empty"); return root; } //end#fragment LinkedTree //begin#fragment LinkedTree2 /** Returns the parent of a node. */ public Position parent(Position v) throws InvalidPositionException, BoundaryViolationException { TreePosition vv = checkPosition(v); Position parentPos = vv.getParent(); if (parentPos == null) throw new BoundaryViolationException("No parent"); return parentPos; } /** Returns an iterable collection of the children of a node. */ public Iterable> children(Position v) throws InvalidPositionException { TreePosition vv = checkPosition(v); if (isExternal(v)) throw new InvalidPositionException("External nodes have no children"); return vv.getChildren(); } /** Returns an iterable collection of the tree nodes. */ public Iterable> positions() { PositionList> positions = new NodePositionList>(); if(size != 0) preorderPositions(root(), positions); // assign positions in preorder return positions; } /** Returns an iterator of the elements stored at the nodes */ public Iterator iterator() { Iterable> positions = positions(); PositionList elements = new NodePositionList(); for (Position pos: positions) elements.addLast(pos.element()); return elements.iterator(); // An iterator of elements } /** Replaces the element at a node. */ public E replace(Position v, E o) throws InvalidPositionException { TreePosition vv = checkPosition(v); E temp = v.element(); vv.setElement(o); return temp; } //end#fragment LinkedTree2 //begin#fragment LinkedTree3 // Additional update methods /** Adds a root node to an empty tree */ public Position addRoot(E e) throws NonEmptyTreeException { if(!isEmpty()) throw new NonEmptyTreeException("Tree already has a root"); size = 1; root = createNode(e,null,null); return root; } /** Swap the elements at two nodes */ public void swapElements(Position v, Position w) throws InvalidPositionException { TreePosition vv = checkPosition(v); TreePosition ww = checkPosition(w); E temp = w.element(); ww.setElement(v.element()); vv.setElement(temp); } // Auxiliary methods //begin#fragment LinkedTree5 /** If v is a good tree node, cast to TreePosition, else throw exception */ protected TreePosition checkPosition(Position v) throws InvalidPositionException { if (v == null || !(v instanceof TreePosition)) throw new InvalidPositionException("The position is invalid"); return (TreePosition) v; } /** Creates a new tree node */ protected TreePosition createNode(E element, TreePosition parent, PositionList> children) { return new TreeNode(element,parent,children); } /** Creates a list storing the the nodes in the subtree of a node, * ordered according to the preorder traversal of the subtree. */ protected void preorderPositions(Position v, PositionList> pos) throws InvalidPositionException { pos.addLast(v); for (Position w : children(v)) preorderPositions(w, pos); // recurse on each child } } //end#fragment LinkedTree5