CS 1723/1721:
Project 3
Binary Trees: Traversals and Drawing
[Due 30 November 2001]
Rules: This is the third of four major individual assignments
that you are required to complete in this class.
You must design and code this project on your
own. You can ask for debugging help, particularly from the tutors, a TA or
the instructor, but this project is to be your own work. The project
relies on previous work with binary trees and with queues.
Overview:
The ultimate goal of this project is to draw a picture of a binary
tree. (This project is similar to Problem 18.12 on pages 601-602
of your text.)
To help with this, you will use tree traversals to calculate
numbers related to the placement of tree nodes. You will also
use traversals to draw the tree itself. Here are individual
portions of the project:
- Traversals used to calculate node numbers:
- Use the supplied software (or other software)
to create a binary tree with a
String at each node, where inorder for
the tree is the same as alphabetic order for the Strings.
(This is known as a binary search tree.
See Binary
Search Tree Example.)
- Use an inorder traversal
to calculate and store in each node the depth of
that node in the tree.
(You could also do this during the insertion in the previous step.)
The depth is the number of tree
links you need to follow from the root to get to the given node,
where the root has depth of 1. (You could instead
assume root has depth 0 if you wish.)
- Use another inorder traversal to calculate and store in
the node the inorder number of each node in the tree,
starting with 1 for the node coming first in inorder.
This essentially gives a count of the nodes, using inorder (the same
as alphabetic order) for the strings at the nodes.
- Use yet another traversal,
this time a level-order traversal
(see below) to calculate
and store in the node the breadth of each node in the tree.
Here the breadth gives a count of the nodes at a given level,
from left-to-right, starting with 1.
(This part is required, but is not needed to draw the tree.)
- Your code must also calculate the maximum depth, the
maximum inorder number, and the maximum breadth.
- Calls to methods that will draw circles and lines to represent
the tree:
- You should imagine horizontal lines, one for each depth
number (as you go down, from depth 1 down
to the maximum depth). Imagine also vertical lines corresponding to
each inorder number,
starting at 1 on the left and counting
up to the maximum inorder number.
Each node should be placed in its proper location, according
to its depth (y-coordinate) and inorder number
(x-coordinate).
- Here is an example image of a drawing of the tree.
This drawing started with 19
strings: the months in order followed by the days in order, each
using only 3 characters, that is,
"Jan", "Feb", "Mar", "Apr", "May",
"Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Mon", "Tue", "Wed",
"Thu", "Fri", "Sat", "Sun", in this order. These were
inserted into the binary search tree before depicting it.
- Example image that uses a separate column for each node:
Inorder example.
- For each node in the tree, call a method
placeCircle(s, row, col);,
where s is the string at the node,
row (the row) is the depth of the node, and
col (the column) is the column number, which
is the inorder number.
- For each line in the tree connecting two nodes, call a method
placeLine(row1, col1, row2, col2);,
where row1 and
col1 give the row and column of the first node,
and row2 and
col2 give the row and column of the
second node.
- This part can have the methods placeCircle
and placeLine just print the locations of
each circle and line.
- Creating a Java applet that will draw
a picture of the tree:
- Write a java applet that will actually draw the circles
and lines inside an applet window. You should draw the lines
first. Then to draw the circle, you can first fill in
a white circle (to erase that part of the line inside the
circle), then a black circular line around the node, and finally
the characters at the node inside the circle (if there is room).
Hand-in Requirements:
- Index cards for:
- The TreeNode class, with extra fields
for the depth, the breadth, and the inorder number.
- The Tree class, with extra methods
doing traverals.
- The TreeTest class, to test the
traversals and to print the node numbers: depth, inorder
number, and breadth (for Part I). You should also print the maximum
depth, the maximum inorder number, and the maximum breadth.
Finally you should print the
information about calls to placeCircle
and placeLine (for Part II).
- The TreeApplet class, to create an applet
to draw a picture of the tree, and
- The PlaceFigures
class, which will implement the methods placeCircle
and placeLine,
called from the Tree class, that do the
drawing.
- Hard-copy source for:
- The TreeNode.java file,
- The Tree.java file,
- The TreeTest.java file,
- The TreeApplet.java file, and
- The PlaceFigures.java file.
- Results of a run of the programs:
- You should turn in a printout of the results of the run
of TreeTest.java, showing printouts of the
numbers for Parts I and II.
- You should also print a screen shot of the appletwindow
showing your drawing of the tree, for Part III.
Supplied Code: You may make use of the following
three programs, whose code is supplied in the links below:
- A binary search tree of Strings:
Binary Search
Tree Example.
This example was intended to be as simple as possible, avoiding
various confusing extra details, such as Comparable
items in the tree and more complex binary tree code. You may
use other binary search tree code if you wish.
- A simple applet demonstration:
Simple Applet.
This is all you need to know about applets to complete tha
project (I think!).
- A more complex applet demonstration (not needed for this project):
Fancier Applet.
This shows a text window for inputting text, a
button to push, and optional code that will keep the applet
from starting from scratch when it updates.
More Detailed Description of the Classes and Methods to be Supplied:
- TreeNode.java: Just add fields
for depth, breadth, and inorder number.
- Tree.java: Add methods to do traversals
that calculate and add numbers to the tree nodes.
There is an inorder traversal to calculate the depth.
This same traversal can also calculate the inorder number.
Finally, a level-order traversal can calculate the breadth.
Level-order traversal: This is a traversal that visits
each level (starting with the root level) before going on to
the next level. Nodes at each level are visited from left to
right.
The traversal is described in your text
on pages 596-598, but not in a way that is readily
comprehensible. However, the basic idea of this traversal
is very simple. Recursion is not needed, but a queue is.
Here is an outline of the algorithm:
add root as last element of queue (initially empty);
while (queue is not empty) {
remove element loc from front of queue;
visit node loc refers to;
if loc.left is not null, then
add it as last element of queue;
if loc.right is not null,
then add it as last element of queue;
}
The first time the above algorithm visits a node with 1 greater
depth, one can start counting the breadth of nodes from 1.
For the queue, you could use the Java library class
LinkedList, with methods addLast,
removeFirst, and size.
- TreeTest.java: Just invoke the various
methods to do everything. You need to print out the numbers
associated with each node, perhaps in the level-order
traversal. Sample numbers for our example tree are:
here.
You also must print the locations for circles and lines:
Sample location numbers are:
here.
- TreeApplet.java: The Java program can
be adapted from the TreeTest program and the DemoApplet program.
Notice that an applet does not have a main method, but invoked
from somewhere like within a browser. Here is a write-up
describing Java applets in more detail:
Java applets.
- PlaceFigures.java: Here one needs code for
methods placeCircle
and placeLine
to draw the nodes and the lines connecting them. As shown in the
demo applet, one can pass the Graphics class
to the Tree class when invoking it.
Then inside Tree you can do the same thing
for the PlaceFigures class.
Sample Input:
As mentioned above, this could be just
String[] a = {"Jan", "Feb", "Mar", "Apr",
"May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec",
"Mon", "Tue", "Wed", "Thu",
"Fri", "Sat", "Sun"};
As alternative input (longer), you could try
String[] a = {"eny", "meny", "miny", "mo",
"ctch", "a", "tigr", "by",
"the", "toe", "if", "he",
"hlrs", "let", "him", "go",
"my", "mthr", "told", "me",
"to", "chse", "very", "best",
"one", "and", "you", "are",
"not", "it"};
Development and Debug Strategy: Obviously you should do
Part I above first, then Part II, and finally work on Part III.
It is not expected that everyone will complete all parts, so if
you do some partial work, you should turn in listings for
partial credit.
Remember: You must use a level-order traversal to
calculate the breath at each node even though you do not use the breadth
in your picture..
Extras for those who would like to do more than the above:
Here are two examples of applets that do more.
- When you type a string into the window and hit return, this
shows in red the nodes that are traversed in looking up the string
in the binary search tree:
Tree with descent
- This starts with no tree and just inserts each string
that you type into a growing binary search tree, which is
displayed:
Tree from scratch
Revision date: 2001-11-12.
(Please use ISO
8601, the International Standard.)