| CSC 207 | Algorithms and Object Oriented Design | Spring 2010 |
Summary: In this lab, you will implement a specialized in-order traversal in order to produce a graph of a tree.
mkdir somewhere/tree
cd somewhere/tree
cp ~weinman/public_html/courses/CSC207/2010S/labs/code/tree/*.java .This should place a graphics class,
TreeGrapher.java,
and two modified data structure
classes BinaryTree.java
and BinaryNode.java into your directory. (Don't worry
if cp complains that it can't copy my solution file
... that's the idea.)
A graphical version of a binary tree can be generated automatically with a relatively simply program by assigning an x,y coordinate to each node. We can then draw a circle at each node's coordinate, and connect each non-root node to its parent with a line between their coordinates. So where do these coordinates come from?
We want the left-most node to have the smallest x-coordinate (0), and the right-most node to have the largest (N, the number of nodes in the tree). The parent of the left-most node should be immediately to the right of it, suggesting the x-coordinate of 1. Continuing in this fashion, we see that the x-coordinate should be the number corresponding to the node's "index" in an in-order traversal.
In most graphics coordinate systems, the origin is in the upper-left corner of the frame. Thus, 0 is the top, and H, the height of the tree, should be at the bottom. What should the y-coordinate be for the root? If it's at the top, presumably it is zero. What about the root's children? Their y-coordinate should be 1. What is the y-coordinate of an arbitrary node? It should be its depth in the tree.
Some drawing primitives will be provided for you. Your task will be to calculate the coordinates of a node using recursive routines to find the depth and in-order traversal number of every node. With these, you will use the drawing commands provided to add circles and lines to a graph for displaying the tree.
TreeGrapher.java contains the following two
routines for indicating where to draw tree nodes and how to connect
them. Study the documentation to be sure you understand how these
methods work.
/** Add circle at a particular coordinate with a label
*
* @param x x-coordinate of circle (i.e., in-order traversal)
* @param y y-coordinate of circle (i.e. depth)
* @param label Any associated text to print with circle
* @return Unique identifier of circle
*/
public int addCircle(int x, int y, String label);
/** Add line to connect two circles
*
* @param i Identifier of first circle to connect with line
* @param j Identifier of second circle to connect with line
* @throws IllegalArgumentException if either circle identifier is invalid
*/
public void addLine( int i, int j);
BinaryTree.java. This is a modified
version of the version from the textbook (Figure 18.13, p. 662).
drawTree. Simply note it has three
calls to methods on the root node. The first calculates the depth
of the root and all its children. The second calculates the in
order traversal number of the root and all its children. The third
generates the drawing using the two values just calculated. Your
job (eventually) will be to implement these methods.
BinaryTree.java (in Emacs, use C-c C-v
C-c).
TreeGrapher has a static method
called start that is called
from BinaryTree.main(). This routine takes
a BinaryTree object, calls the drawTree
method and generates a window containing the tree. Thus, all you
will need to do is construct a tree (one is provided already) and
call this method. That is, after you implement the methods called
in the step above. The default tree looks like this (which will
eventually be the result of your program).

TreeGrapher.java (in Emacs, use C-c C-v
C-c).
BinaryNode.java. Note that two private
fields have been added, order, to store the in-order
traversal number of a node, and depth, to store the
depth of a node in the tree.
assignDepth and study its
documentation/specification. Pay careful attention to the meaning
of the parameter, and its value in the call to the root
from BinaryTree.
BinaryNode.java (in Emacs, use C-c C-v
C-c).
BinaryTree.java buffer and run it from
emacs. (Use C-c C-v C-r). An empty window should
appear. Your Emacs buffer should also split and show you the
textual output of your program.
assignDepth
method. Otherwise you will probably want to comment out your print
statement.
order). Locate the
method assignInOrder and study its
documentation/specification. Pay extra-careful attention
(seriously!) to the meaning of the parameter, and its value in the
call to the root from BinaryTree. Also pay
attention to the documented return value (seriously! You
do NOT want Picasso-esque trees).
end to store the "end" (largest)
traversal number for this node (eventually, the value to be returned).
this.order with the result returned.
end
(return) value be? Add a test and assignment to handle this case.
end (return) value
for this node be?
BinaryNode.java (in Emacs, use C-c C-v
C-c).
BinaryTree.java buffer and run it from
emacs. (Use C-c C-v C-r). An empty window should appear.
Your Emacs buffer should also split and show you the textual
output of your program.
assignOrder method. Otherwise you will
probably want to comment out your print statement.
addGraphNode and study its
documentation/specification. Recall that the
method addCircle from TreeGrapher
returns a circle identifier..
TreeGrapher object with the appropriate
coordinates. Use the toString method of
the element to create a label for the circle. Note
the return value for addGraphNode!
addLine method
of TreeGrapher) to connect this node's circle to its
left child's circle.
BinaryNode.java (in Emacs, use C-c C-v
C-c).
BinaryTree.java buffer and run it from
emacs. (Use C-c C-v C-r). Now your window should appear
with your tree. If the order and depth values were correct, and
you used the correct coordinates when adding circles, your nodes
should be in the right places. If you added lines connecting the
appropriate circles, your lines should also be in the right
places. If they are not, study the picture carefully and try to
identify the errors in your addGraphNode routine.
BinaryTree and BinaryNode
classes that implement Exercises 18 c, d, and e. Test each method as
you develop it by creating a driver class that builds some appropriate
trees to test in main. Note that for parts d and e, you may assume that the element IS-A Comparable.