139 lines
4.9 KiB
Java
139 lines
4.9 KiB
Java
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<E> implements Tree<E> {
|
|
protected TreePosition<E> 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<E> v) throws InvalidPositionException {
|
|
return !isExternal(v);
|
|
}
|
|
//end#fragment LinkedTree
|
|
/** Returns whether a node is external. */
|
|
public boolean isExternal(Position<E> v) throws InvalidPositionException {
|
|
TreePosition<E> 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<E> v) throws InvalidPositionException {
|
|
checkPosition(v);
|
|
return (v == root());
|
|
}
|
|
//begin#fragment LinkedTree
|
|
/** Returns the root of the tree. */
|
|
public Position<E> 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<E> parent(Position<E> v)
|
|
throws InvalidPositionException, BoundaryViolationException {
|
|
TreePosition<E> vv = checkPosition(v);
|
|
Position<E> 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<Position<E>> children(Position<E> v)
|
|
throws InvalidPositionException {
|
|
TreePosition<E> 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<Position<E>> positions() {
|
|
PositionList<Position<E>> positions = new NodePositionList<Position<E>>();
|
|
if(size != 0)
|
|
preorderPositions(root(), positions); // assign positions in preorder
|
|
return positions;
|
|
}
|
|
/** Returns an iterator of the elements stored at the nodes */
|
|
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(); // An iterator of elements
|
|
}
|
|
/** Replaces the element at a node. */
|
|
public E replace(Position<E> v, E o)
|
|
throws InvalidPositionException {
|
|
TreePosition<E> 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<E> 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<E> v, Position<E> w)
|
|
throws InvalidPositionException {
|
|
TreePosition<E> vv = checkPosition(v);
|
|
TreePosition<E> 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<E> checkPosition(Position<E> v)
|
|
throws InvalidPositionException {
|
|
if (v == null || !(v instanceof TreePosition))
|
|
throw new InvalidPositionException("The position is invalid");
|
|
return (TreePosition<E>) v;
|
|
}
|
|
/** Creates a new tree node */
|
|
protected TreePosition<E> createNode(E element, TreePosition<E> parent,
|
|
PositionList<Position<E>> children) {
|
|
return new TreeNode<E>(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<E> v, PositionList<Position<E>> pos)
|
|
throws InvalidPositionException {
|
|
pos.addLast(v);
|
|
for (Position<E> w : children(v))
|
|
preorderPositions(w, pos); // recurse on each child
|
|
}
|
|
}
|
|
//end#fragment LinkedTree5
|