package net.datastructures;
import java.util.ArrayList;
import java.util.Iterator;
/**
* A speedy implementation of the CompleteBinaryTree interface using
* a vector. Within the vector, there is a null element at rank 0,
* the root of the tree at rank 1, and the rest of the tree is
* contained as follows. If node n has rank i,
* then the left child of n will have rank 2*i,
* and the right child of n will have rank 2*i +
* 1. Traversing the contents of the vector in order of increasing
* rank yields a level-order traversal
*
* @author Michael Goodrich, Eric Zamore
* @see BinaryTree
* @see CompleteBinaryTree
*/
//begin#fragment VectorHeap
public class ArrayListCompleteBinaryTree
implements CompleteBinaryTree {
protected ArrayList> T; // indexed list of tree positions
/** Nested class for a index list-based complete binary tree node. */
protected static class BTPos implements Position {
E element; // element stored at this position
int index; // index of this position in the array list
public BTPos(E elt, int i) {
element = elt;
index = i;
}
public E element() { return element; }
public int index() { return index; }
public E setElement(E elt) {
E temp = element;
element = elt;
return temp;
}
//end#fragment VectorHeap
public String toString() {
return("[" + element + "," + index + "]");
}
//begin#fragment VectorHeap
}
/** default constructor */
public ArrayListCompleteBinaryTree() {
T = new ArrayList>();
T.add(0, null); // the location at rank 0 is deliberately empty
}
/** Returns the number of (internal and external) nodes. */
public int size() { return T.size() - 1; }
/** Returns whether the tree is empty. */
public boolean isEmpty() { return (size() == 0); }
//end#fragment VectorHeap
//begin#fragment VectorHeap2
/** Returns whether v is an internal node. */
public boolean isInternal(Position v) throws InvalidPositionException {
return hasLeft(v); // if v has a right child it will have a left child
}
/** Returns whether v is an external node. */
public boolean isExternal(Position v) throws InvalidPositionException {
return !isInternal(v);
}
/** Returns whether v is the root node. */
public boolean isRoot(Position v) throws InvalidPositionException {
BTPos vv = checkPosition(v);
return vv.index() == 1;
}
/** Returns whether v has a left child. */
public boolean hasLeft(Position v) throws InvalidPositionException {
BTPos vv = checkPosition(v);
return 2*vv.index() <= size();
}
/** Returns whether v has a right child. */
public boolean hasRight(Position v) throws InvalidPositionException {
BTPos vv = checkPosition(v);
return 2*vv.index() + 1 <= size();
}
/** Returns the root of the tree. */
public Position root() throws EmptyTreeException {
if (isEmpty()) throw new EmptyTreeException("Tree is empty");
return T.get(1);
}
/** Returns the left child of v. */
public Position left(Position v)
throws InvalidPositionException, BoundaryViolationException {
if (!hasLeft(v)) throw new BoundaryViolationException("No left child");
BTPos vv = checkPosition(v);
return T.get(2*vv.index());
}
/** Returns the right child of v. */
public Position right(Position v)
throws InvalidPositionException {
if (!hasRight(v)) throw new BoundaryViolationException("No right child");
BTPos vv = checkPosition(v);
return T.get(2*vv.index() + 1);
}
//end#fragment VectorHeap2
//begin#fragment VectorHeap3
/** Returns the parent of v. */
public Position parent(Position v)
throws InvalidPositionException, BoundaryViolationException {
if (isRoot(v)) throw new BoundaryViolationException("No parent");
BTPos vv = checkPosition(v);
return T.get(vv.index()/2);
}
//end#fragment VectorHeap3
/** Returns an iterable collection of the children of v. */
public Iterable> children(Position v) throws InvalidPositionException {
PositionList> children = new NodePositionList>();
if (hasLeft(v))
children.addLast(left(v));
if (hasRight(v))
children.addLast(right(v));
return children;
}
/** Returns an iterable collection of all the nodes in the tree. */
public Iterable> positions() {
ArrayList> P = new ArrayList>();
Iterator> iter = T.iterator();
iter.next(); // skip the first position
while (iter.hasNext())
P.add(iter.next());
return P;
}
//begin#fragment VectorHeap3
/** Replaces the element at v. */
public E replace(Position v, E o) throws InvalidPositionException {
BTPos vv = checkPosition(v);
return vv.setElement(o);
}
/** Adds an element just after the last node (in a level numbering). */
public Position add(E e) {
int i = size() + 1;
BTPos p = new BTPos(e,i);
T.add(i, p);
return p;
}
/** Removes and returns the element at the last node. */
public E remove() throws EmptyTreeException {
if(isEmpty()) throw new EmptyTreeException("Tree is empty");
return T.remove(size()).element();
}
/** Determines whether the given position is a valid node. */
protected BTPos checkPosition(Position v)
throws InvalidPositionException
{
if (v == null || !(v instanceof BTPos))
throw new InvalidPositionException("Position is invalid");
return (BTPos) v;
}
//end#fragment VectorHeap3
// Additional Methods
/** Returns the sibling of v. */
public Position sibling(Position v)
throws InvalidPositionException, BoundaryViolationException {
try {
Position p = parent(v);
Position lc = left(p);
if (v == lc)
return right(p);
else
return lc;
}
catch(BoundaryViolationException e) {
throw new BoundaryViolationException("Node has no sibling");
}
}
/** Swaps the elements at two nodes. */
public void swapElements(Position v, Position w)
throws InvalidPositionException {
BTPos vv = checkPosition(v);
BTPos ww = checkPosition(w);
E temp = vv.element();
vv.setElement(ww.element());
ww.setElement(temp);
}
//begin#fragment VectorHeap3
/** Returns an iterator of the elements stored at all nodes in the tree. */
public Iterator iterator() {
ArrayList list = new ArrayList();
Iterator> iter = T.iterator();
iter.next(); // skip the first element
while (iter.hasNext())
list.add(iter.next().element());
return list.iterator();
}
//end#fragment VectorHeap3
/** Returns a String representing this complete binary tree. */
public String toString() { return T.toString(); }
//begin#fragment VectorHeap3
}
//end#fragment VectorHeap3