package brs; /** * Models the binary tree structure using the state pattern and the visitor * pattern. Provides only structural behaviors and a hook to execute any * visitor algorithm. * Exercise: Override the toString() method anonymous inner visitor classes. * @author Dung X. Nguyen - Copyright 2002 - All rights reserved. * @author Mathias Ricken - Copyright 2008 - All rights reserved. */ public class BiTree { /** * the state of this BiTree. */ private ANode _rootNode; /** Visitor to generate string representation. */ private ToString _toString = new ToString(); /** * Initializes this BiTree to the empty state. */ public BiTree() { _rootNode = new EmptyNode(); } /** * Gets the root data of this BiTree if it exists. * @return the root data element of this BiTree if it exists. * @exception NoSuchElementException if this BiTree is empty. */ public T getRootDat() { return _rootNode.getRootDat (this); } /** * Sets the root data element to a given object. * @param dat the new root data. * @exception NoSuchElementException if this BiTree is empty. */ public void setRootDat(T dat) { _rootNode.setRootDat (this, dat); } /** * Gets the left subtree of this BiTree if it exists. * @return the left subtree of this BiTree if it exists. * @exception NoSuchElementException if this BiTree is empty. */ public BiTree getLeftSubTree() { return _rootNode.getLeftSubTree (this); } /** * Gets the right subtree of this BiTree if it exsists. * @return the right subtree of this BiTree if it exists. * @exception NoSuchElementException if this BiTree is empty. */ public BiTree getRightSubTree() { return _rootNode.getRightSubTree (this); } /** * Attaches a new left subtree to the left of this BiTree, allowing this * BiTree to grow to the left. * @param biTree to replace the current left subtree. * @exception NoSuchElementException if this BiTree is empty. */ public void setLeftSubTree(BiTree biTree) { _rootNode.setLeftSubTree(this, biTree); } /** * Attaches a new right subtree to the left of this BiTree, allowing this * BiTree to grow to the right. * @param biTree to replace the current right subtree. * @exception NoSuchElementException if this BiTree is empty. */ public void setRightSubTree(BiTree biTree) { _rootNode.setRightSubTree(this, biTree); } /** * Inserts a root element to this BiTree. * Allows for state change from empty to non-empty. * @param dat the new root data. * @exception IllegalStateException if this BiTree has more than one element. */ public void insertRoot(T dat) { _rootNode.insertRoot(this, dat); } /** * Removes and returns the root data element of this BiTree. * @return the root data element of this BiTree. * @exception NoSuchElementException if this BiTree is empty. * @exception IllegalStateException if one of the subtrees is not empty. */ public T remRoot() { return _rootNode.remRoot(this); } /** * Hook to execute any algorithm that presents itself as a visitor to this * BiTree. * @param algo a visitor to a BiTree. * @param inp the vararg input for the algo visitor. * @return the output for the execution of algo. */ public R execute(IVisitor algo, P... inp) { return _rootNode.execute(this, algo, inp); } public String toString () { return (String)execute(_toString); // EXERCISE FOR STUDENTS: The above line of code does not conform to the // state pattern because it does not forward the request to the state. // Rewrite the code to conform to the state pattern. You will need to add // appropriate methods to the states. Review what we did with toString() // for linear recursive structures. } /** * Changes this BiTree to a given new node (i.e. state). * @param node a new root node (i.e.state) for this BiTree. */ final void setRootNode(ANode node) { _rootNode = node; } /** * Returns the current node (i.e. state) of this BiTree. * @return the current root node (state) of this BiTree. */ final ANode getRootNode() { return _rootNode; } }