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