Copyright © Cay S. Horstmann 2012 
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 United
States License.
java Trees1 10 and java Trees1 20.)seq—see Lab 9.)Complete this program. (You need the
BinaryTree class from Chapter 17 Section 2.)
What is the code of your randomTree method?
toString method, and we will do that
presently. But first, let's look at the tree in the debugger. Set a
breakpoint at the last line of main and run the program. Get
out a sheet of paper. Inspect t. Keep expanding the
left and right nodes. From the display, sketch
the tree, like you did in Lab 7.
Hand the sketch to the lab instructor.
toString method. Ideally, we might like
something like
6
/ \
3 2
/ \ \
1 1 1
but that's pretty hard to do in general. Instead, let's have a one-dimensional representation, something of the form
left subtree data right subtree
Let's do that. Add a method
public String toString()
to the BinaryTree class. It must call a recursive method on
the root node. Let's call it toString as well:
public static String toString(Node n)
That's where the actual work gets done. (Look at height as
another example of how this is done.)
In the Node.toString method, return a string as described
above, with the left, data, and right separated by spaces. If the node is
null, return ".".
What is your code?
(left subtree data right subtree)
Do this. What is your output now?
((. 2 (. 1 .)) 6 ((. 1 .) 3 (. 1 .)))
Draw the correspnding tree.
for (BinaryTree t1 : l1)
{
for (BinaryTree t2 : l2)
{
BinaryTree t = new BinaryTree(n, t1, t2);
...
}
}
Put each tree in a list l and return it.
Complete the allTrees method in this class. What is your code?
wc, as
shown in Lab 9.)Problem #1. The BinarySearchTree class in Chapter 17 Section 3 is different from the BinaryTree class that we used so far.
Why can't we just change BinaryTree to
BinarySearchTree in Trees3?
BinarySearchTree have a constructor
public BinarySearchTree(Object rootData, BinarySearchTree left, BinarySearchTree right)
private
from
private Node root;
in BinarySearchTree. Now root (and the
Node class) are package-visible. When we add a class
Trees4 to the default package, it can access the
root field.
Next, declare the Node class as static:
static class Node
This is a very technical detail—it means that a Node can
be constructed outside a BinarySearchTree.
For example, suppose you have trees t1 and t2,
and now you want to make a new tree with both of them, you can use this
brute-force code:
BinarySearchTree t = new BinarySearchTree(); t.root = new BinarySearchTree.Node(); t.root.left = t1.root; t.root.right = t2.root;
Not very object-oriented, but it's ok for a test harness that is meant to test the internals of the implementation.
Using this technique, make a copy of Trees3, call it Trees4, change all
BinaryTree to BinarySearchTree, and construct the trees as described above.
Also set t.root.data = n in the second and third branch;
e.g.
for (BinarySearchTree t1 : l1)
{
for (BinarySearchTree t2 : l2)
{
BinarySearchTree t = new BinarySearchTree();
t.root = new BinarySearchTree.Node();
t.root.data = n;
...
}
}
What does your program print? Why?
toString to the BinarySearchTree class.
In toString, you can't just use print. Why?toString in the same way as you did before. Now
what does your program print? Here is our problem. We have a tree like
*
/ \
* *
/ \ \
* * *
and now we want to fill in the data
4
/ \
2 5
/ \ \
1 3 6
Here is a recursive way of doing it. Look at the root. Fill in the left subtree, starting with 1, and have the recursive call tell you the next number to be used (4 in the example). Then fill in the root with the that data. Then fill in the right subtree starting with the next value (here 5). And ask it what its next number is (7). Return that number to the caller.
In Trees4, Implement a method
public static int fill(BinarySearchTree.Node n, int start)
that uses this strategy. What is your code?
fill(t.root, 1);
in main. What is your printout?
main method to
public static void main(String[] args)
{
List<BinarySearchTree> trees = allTrees(6);
int k = 1;
for (BinarySearchTree t : trees)
{
fill(t.root, k);
k++;
}
for (BinarySearchTree t : trees)
{
System.out.println(t);
}
}
What values to you expect to have in the first tree? The second tree? The kth tree?

Then the second mutation overwrites the first.
Let's see if we have shared nodes in our trees.
When you make a new Node, you get a fresh, new one. Where
does that happen in allTrees?
a.left = n;
then both a.left and n point to the same node.
Where does that happen in allTrees?
remove method, which we want to test, mutates the tree on
which it operates.
So, we need to make a copy of each tree.
Copying a tree seems generally useful, so let's add a method
public BinarySearchTree copy()
to the BinarySearchTree class.
How do you copy a tree? You construct a new root node and populate it with copies of the left and right subtrees. That's best done in a recursive method
public Node copy(Node n)
{
if (n == null) return null;
else
{
Node newRoot = ...;
...
...
...
return newRoot;
}
}
Add the copy methods to the BinarySearchTree
class. What are your complete methods?
System.out.println(t);
in Trees4 to
System.out.println(t.copy());
If you did everything right, you should get the same output.
remove
method. Here's the plan. For a given n,
Add a JUnit class RemoveTest to your NetBeans project. What
did you do to do that?
RemoveTest class
public void testRemove(int n)
Do just what the pseudocode did. Call Trees4.allTrees,
Trees4.fill, find (in the
BinarySearchTree), assertTrue, and
assertFalse (from JUnit).
What is your method?
@Test. What happens if you add @Test to
public void testRemove(int n)?@Test and add
@Test public void testRemove6()
{
testRemove(6);
}
What happens?
remove method
worked. Just to see what happens when there is an error, locate the
if statement
if (toBeRemoved.left == null)
{
newChild = toBeRemoved.right;
}
in BinarySearchTree.remove and inside the body, change
right to left. Run the test again. What
happens?
remove method. When you look at section
17.3.3 of your textbook, you will notice that the case “Removing a node
with two children” makes an arbitrary choice. The node to be removed is
replaced with the smallest value in the right subtree, when it could
equally well be replaced with the largest value in the left subtree.
Consider this BST:
2
/ \
1 7
/ \
4 11
/ \ / \
3 5 10 12
\ /
6 8
\
9
We want to remove 7.
How does the removal unfold, as described in the book?
remove method to do that. List all the
changes that you had made.