Due by 6PM on Sunday, April 17
In this lab you will implement a recursive binary tree structure and associated methods. The purpose of this lab is to:
You should get the starter code from Lab5.zip. As with previous labs, you want to unzip this into your csci151 folder. It makes a folder named "Lab5"; change the name of this folder to "Lab5<your last name> and open up an Eclipse project named Lab5 with this as your project folder. You will find the following files:
The BinaryTree, EmptyTree, and ConTree classes create a binary tree data structure. You will be adding methods to each of these classes. The TreeLoader class has a method loadTreeFromFile that you need to implement in Part 2. The The other three files create a GUI interface; you should not need to change them.
As you may recall from class, a binary tree is either:
The starter code creates three tree classes:
You should be able to run the TreeApp program. It doesn't do much yet. There is a Load File button that brings up a file picker that allows you to choose from various tree files that have been supplied, but nothing happens when you choose a file because the loadTreeFromFile() method at this point just returns a new EmptyTree. You will fix that in Part 2.
This application's GUI frame has two text areas for output, and a group of buttons for user commands. After you implment the loadTreeFromFile() method, when a file is loaded a binary tree object will be created and the tree displayed in the left area of the frame. The area on the right side of the frame is used for the output the methods you will implement in Part 3.
Your task for this part is to implement the loadTreeFromFile() method in the TreeLoader class. We'll walk you through it.
The tree files for this lab list the nodes of the tree in postorder sequence, one node per line. Each line contains a string, which is the data value stored in the node, and two tag bits. The first tag bit indicates whether or not this node has a left child or not. (1=yes, 0=no). The second tag bit indicates whether the node has a right child or not.
For example, tree7:
is represented as
32 0 0 74 0 1 29 0 0 63 1 0 18 0 0 83 1 1 34 1 1
The information in the file is sufficient to uniquely determine a binary tree. The tree can be constructed from the file using the following algorithm:
Stack<BinaryTree<String>>
)When you exit the while loop after having read all of the input, the stack should contain one element. This element is the the tree represented by the file, so return it. If the stack is empty, the tree has no nodes, so the tree must be an EmptyTree.
NOTE: the input file is left then right, but the algorithm uses the right value first, then the left. This is not a typo.
You need to implement this algorithm in the loadTreeFromFile method, with the following method signature:
public BinaryTree<String> loadTreeFromFile(String filename)
The method should create a Scanner object to read strings from the file whose name is given as an argument. It should create a Stack of BinaryTree<String> objects to use as a work area. You can use Java's standard Scanner and Stack classes.
NOTE: Use Java generics in your code when declaring and instantiating a tree or stack. (For example, use BinaryTree<String> and Stack<BinaryTree<String>>.)
Test out your program, using the TreeApp program.
Each of the methods listed below appears in the BinaryTree class as an
abstract method. Eclipse has given default implementations of them in ConsTree
and EmptyTree
. Your task for each method is to provide correct
implementations in ConsTree
and EmptyTree
and test that they work using
the provided tree files.
Note: You do not need any loops in any of these methods.
Here is the complete list of methods for you to implement.
public boolean isEmpty()
true
if the tree is empty. (You should know this based on the
class itself.)public int height()
public int nodeCount()
public int leafCount()
public int levelCount(int level)
public int diameter()
In the third case, the longest path must include the root and therefore must be from the deepest leaf on the left to the deepest leaf on the right. We can compute that as the height of the left subtree plus the height of the right subtree plus 2. (We have to add 2 because the path from the left child → root → right child has length 2.)
public BinaryTree<T> mirrorImage()
clone()
method for Collections
, the new tree should contain all new
nodes, not sharing any with the original tree. However, the data objects in
the tree should be the same objects as those in the original tree; those
objects should not be cloned. (This is also known as a shallow copy.)public BinaryTree<T> pare()
For example, if we pare tree7.txt
the tree changes from
to .
Nodes 74 and 63 have one child each and
thus the whole subtree corresponding to those children will be removed
leaving the result on the right
Paring tree9.txt
will remove every node except for the root because the
root only has a single child.
Paring any tree a second time should not change the tree since all nodes will have either zero or two children. (This is called a full binary tree.)
public BinaryTree<T> cutLeaves()
mirrorImage()
and pare()
, the copy of the data should
be shallow. Cutting the leaves of tree7.txt
removes nodes 32, 29, and 18, leaving this.
.
Unlike pare()
, cutLeaves()
can be performed multiple times and each time
will reduce the number of nodes in the tree until the tree is empty.
public int weightBalanceFactor()
Define the weight-balance factor of a binary tree as follows: it is the maximum value of the absolute value of (number of nodes in left subtree minus number of nodes in right subtree) for all nodes in the tree. Whew! That takes some parsing!
Note: This is a different measurement from the Height-Balance property of AVL trees.
Here is an annotated example showing the WBF of all the nodes. (When you
click the Weight Balance Factor
button, you won’t see these annotations.)
public void preOrderElements(List<T> list)
public void postOrderElements(List<T> list)
public void inOrderElements(List<T> list)
Note: The last three methods take a list as a parameter and append to it, rather than creating a new list and returning it: this is to avoid creating multiple lists. This also lets you implement these methods recursively.
Look through your programs and make sure you've included your name at the top of ConsTree.java, EmptyTree.java and TreeLoader.java, the three files you edited.
Include in your submission a file named README. The contents of the README file should include the following:
As usual, make a zipped copy of you project folder (which should be Lab5<your last name>) and hand it in on Blackbard as Lab 5.