Rev 100 | Blame | Compare with Previous | Last modification | View Log | RSS feed
// Written by Ira Snyder// Due Date: 11-15-2004// Project #3// People Helped: Allen Oliver// License: Public Domain (added 07-11-2005)import java.io.*;import java.util.*;class BinaryTree {private Object root;private BinaryTree left, right;//constructors ----------------------------------------------------------// constructor to create a singleton tree// Precondition: root is a non-null Object// Postcondition: returns a BinaryTree with the Object given as the root// data, and null left and right subtreespublic BinaryTree( Object root ) {this.root = root;this.left = null;this.right = null;}// constructor to create a BinaryTree with the given Object as the root// data, and the given BinaryTrees as the left and right subtrees// Precondition: root is a non-null Object (right and left CAN be null// Postcondition: returns a BinaryTree with the given root data and// the given left and right subtreespublic BinaryTree( Object root, BinaryTree left, BinaryTree right ) {this.root = root;this.left = left;this.right = right;}// copy constructor, creates a tree which has the same structure and// whose nodes reference the same objects as the _that_ treepublic BinaryTree( BinaryTree that ) {root = that.root;left = null; right = null;if( that.left != null ) { left = new BinaryTree(that.left); }if( that.right != null ) { right = new BinaryTree(that.right); }}//getter methods --------------------------------------------------------// method which returns the root data// Precondition: none// Postcondition: return the root datapublic Object getRoot() { return root; }// method which will return a reference to the left subtree// Precondition: none// Postcondition: returns a reference to the left subtreepublic BinaryTree getLeft() { return left; }// method which will return a reference to the right subtree// Precondition: none// Postcondition: returns a reference to the right subtreepublic BinaryTree getRight() { return right; }//setter methods --------------------------------------------------------// method which updates the root data// Precondition: root is non-null// Postcondition: sets this.root to the new data, returns the old datapublic Object setRoot( Object root ) {Object temp = this.root;this.root = root;return temp;}// method which updates the left subtree// Precondition: none ( left CAN be null )// Postcondition: sets this.left to the new subtree,// returns a reference to the old left subtreepublic BinaryTree setLeft( BinaryTree left ) {BinaryTree temp = this.left;this.left = left;return temp;}// method which update the right subtree// Precondition: none ( right CAN be null )// Postcondition: sets this.right to the new subtree,// returns a reference to the old right subtreepublic BinaryTree setRight( BinaryTree right ) {BinaryTree temp = this.right;this.right = right;return temp;}//toString method -------------------------------------------------------// returns a String representation of the BinaryTree// Precondition: none// Postcondition: returns a string representation of the BinaryTreepublic String toString() {String sLeft = "";String sRight = "";String answer = new String();//get the left tree's string representation (if it exists)if( !(left == null) ) { sLeft = left.toString(); }//get the right tree's string representation (if it exists)if( !(right == null) ) { sRight = right.toString(); }//assemble the string to returnanswer = "(";if( !sLeft.equals("") ) { answer += sLeft + ","; }answer += root.toString();if( !sRight.equals("") ) { answer += "," + sRight; }answer += ")";//return the assembled stringreturn answer;}//misc methods ----------------------------------------------------------// method to check if the current node is a leaf// Precondition: none// Postcondition: returns true if the current node is a leaf, and false// in any other casepublic boolean isLeaf() {if( (left == null) && (right == null) ) { return true; }return false;}// method to find the size of the tree// Precondition: none// Postcondition: returns the size of the treepublic int size() {int answer=1; // 1 for the node we are atif( !(left == null) ) { answer += left.size(); }if( !(right == null) ) { answer += right.size(); }return answer;}// method to calculate the height of the tree// Precondition: none// Postcondition: returns the height of the treepublic int height() {if( this.isLeaf() ) { return 0; }int l=0,r=0;if( left != null ) { l = 1 + left.height(); }if( right != null ) { r = 1 + right.height(); }return Math.max(l,r);}// method to search the tree for an object// Precondition: object is non-null// Postcondition: returns true if the tree contains the object,// and false if the tree doesn't contain the objectpublic boolean contains( Object object ) {if( root.equals(object) ) { return true; }//if( this.isLeaf() ) { return false; }boolean l=false, r=false;if( left != null ) { l=left.contains(object); }if( right != null ) { r=right.contains(object); }return l || r;}// method to find the number of leaves in the tree// Precondition: none// Postcondition: returns the number of leaves in the treepublic int numLeaves() {if( this.isLeaf() ) { return 1; }int l=0, r=0;if( left != null ) { l = left.numLeaves(); }if( right != null ) { r = right.numLeaves(); }return l + r;}// method to find the number of a certain object in the tree// Precondition: the object in non-null// Postcondition: returns the number of the object that// are in the treepublic int count( Object x ) {int answer=0;if( root.equals(x) ) { answer=1; }if( !(left == null) ) { answer += left.count(x); }if( !(right == null) ) { answer += right.count(x); }return answer;}// method to check if the tree is full// Precondition: none// Postcondition: returns true if the tree is a full tree,// and false if the tree is not a full treepublic boolean isFull() {if( this.isLeaf() ) { return true; }if( !(left.height() == right.height()) ) { return false; }if( left.isFull() && right.isFull() ) { return true; }return false;}// method to check if the tree is balanced// Precondition: none// Postcondition: returns true if the tree is balanced, false otherwisepublic boolean isBalanced() {if( this.isLeaf() ) { return true; }//get left and right heights as applicableint l=0, r=0;if( left != null ) { l = left.height(); }if( right != null ) { r = right.height(); }//check for the criteria of balance. If we are balanced, then//check our subtrees for balance recursivelyif( Math.abs( l-r ) < 2 ) {if( left != null && right != null ) //check bothreturn left.isBalanced() && right.isBalanced();if( left != null ) //right is null (check left)return left.isBalanced();//left is null, right is not nullreturn right.isBalanced(); //check right}return false; //the criteria of balance was not met}// method to get the total path length of the current tree// Precondition: none// Postcondition: returns the sum of all the root to node paths in// the treepublic int pathLength() {int answer=0;Queue queue = new Queue();queue.enqueue(this);while( !queue.isEmpty() ) {BinaryTree temp = (BinaryTree)queue.dequeue();answer += level(temp.root);if( temp.left != null ) { queue.enqueue(temp.left); }if( temp.right != null ) { queue.enqueue(temp.right); }}return answer;}// method to create a reverse of the tree// Precondition: none// Postcondition: returns a new BinaryTree with the structure// reversed as if it were seen in a mirrorpublic BinaryTree reverse() {//both left and right are nullif( this.isLeaf() ) { return new BinaryTree(root); }//left must be null, right must not be nullif( this.left == null )return new BinaryTree(root,right.reverse(),null);//right must be null, left must not be nullif( this.right == null )return new BinaryTree(root,null,left.reverse());//both sides are not nullreturn new BinaryTree(root,right.reverse(),left.reverse());}// a method to find the level of an object in the tree// Precondition: x is not null// Postcondition: returns the level of the deepest object x in the treepublic int level( Object x ) {if( !this.contains(x) ) { return -1; } //not foundif( this.root.equals(x) ) { return 0; } //found hereint ansLeft=0, ansRight=0;if( left != null ) { ansLeft = left.level(x); }if( right != null ) { ansRight = right.level(x); }int answer = Math.max(ansLeft,ansRight);if( answer >= 0 ) { return answer + 1; }return answer;}// method to check if the current tree is disjoint from "that" tree// disjoint: no element in both this tree and that tree// Precondition: none// Postcondition: returns true if and only if no element from "that"// tree is in "this" treepublic boolean isDisjointFrom( BinaryTree that ) {if( that == null ) { return true; }if( this.contains(that.root) ) { return false; }return isDisjointFrom(that.left) && isDisjointFrom(that.right);}// method to check if a tree is valid// valid: all of it's subtrees are disjoint// Precondition: none// Postcondition: returns true if the tree is valid, false otherwisepublic boolean isValid() {if( this.isLeaf() ) { return true; }boolean answer;if( left != null ) { answer = left.isDisjointFrom(right); }else { answer = right.isDisjointFrom(left); }return answer;}// method to check if one tree is equal to another// Precondition: object should be a BinaryTree (this is checked anyway)// Postcondition: return true only if both trees are equalpublic boolean equals( Object object ) {//if we are not a BinaryTree, return falseif( !(object instanceof BinaryTree) ) { return false; }BinaryTree x = (BinaryTree)object; //typed instance of Object//temporary answer holding variablesboolean ansLeft=false, ansRight=false;//check for the root data equalityif( !this.root.equals(x.root) ) { return false; }if( left != null ) { //check leftif( left.equals(x.left) ) { ansLeft = true; }}if( right != null ) { //check rightif( right.equals(x.right) ) { ansRight = true; }}//if both are null, we are still okayif( left == null && x.left == null ) { ansLeft = true; }if( right == null && x.right == null ) { ansRight = true; }//check that both left and right are okayif( ansLeft == true && ansRight == true ) { return true; }return false; //return false if any condition was not met}//printing methods ------------------------------------------------------// method to print the tree in the following order: root,left,right// Precondition: none// Postcondition: the tree will be printed to System.out in preOrderpublic static void preOrderPrint( BinaryTree tree ) {System.out.print( tree.root + " " );if( tree.left != null ) { preOrderPrint( tree.left ); }if( tree.right != null ) { preOrderPrint( tree.right ); }}// method to print the tree in the following order: left,right,root// Precondition: none// Postcondition: the tree will be printed to System.out in postOrderpublic static void postOrderPrint( BinaryTree tree ) {if( tree.left != null ) { postOrderPrint( tree.left ); }if( tree.right != null ) { postOrderPrint( tree.right ); }System.out.print( tree.root + " " );}// method to print the tree by level// Precondition: none// Postcondition: the tree will be printed to System.out by levelpublic static void levelOrderPrint( BinaryTree tree ) {Queue queue = new Queue();queue.enqueue(tree);while( !queue.isEmpty() ) {BinaryTree temp = (BinaryTree)queue.dequeue();System.out.print( temp.root + " " );if( temp.left != null ) { queue.enqueue(temp.left); }if( temp.right != null ) { queue.enqueue(temp.right); }}}// method to print the tree in the following order: left,root,right// Precondition: none// Postcondition: the tree will be printed to System.out in inOrderpublic static void inOrderPrint( BinaryTree tree ) {if( tree.left != null ) { inOrderPrint(tree.left); }System.out.print( tree.root + " " );if( tree.right != null ) { inOrderPrint(tree.right); }}}