CMPS 144 Spring 2020
Lab #10: Binary Search Trees and Family Trees

Activity #1: Binary Search Trees

               40 
              /  \
             /    \
            /      \
           /        \
          /          \
         /            \
        /              \
       /                \
     20                  58
    /  \                /  \
   /    \              /    \
  /      \            /      \
 /        \          /        \
4          29      47          67
 \        /  \       \        /  \
  10    25    35      52    60    73
 /  \        /
6    12    32
 \
  8
The problems associated to this activity were intended to be answered using "pen and paper", but you can put your answers into a plain text file or Word document, or whatever. All the problems relate to the binary search tree shown to the right.

1. Show what the tree would look like after doing each of the following operations. (Note: Each operation should be applied to the original tree shown to the right, not to the tree resulting from performing the previous operation(s).)

You need not reproduce the entire tree each time, but you should show enough surrounding context to make it clear which part of the tree was affected by the operation and what changes occurred there.

(a) Insert 44
(b) Remove 25
(c) Remove 4
(d) Remove 40

2. Below are two methods, each of which recursively traverses a binary tree and prints the values stored in the tree's nodes. Notice the difference between the two in their respective else-branches.

(a) Show the output produced by printInOrder() when applied to the tree shown above.

(b) Show the output produced by printPreOrder() when applied to the tree shown above.

printInOrder()printPreOrder()
public static void printInOrder(BinTree t) {
   if (t.isEmpty()) { }
   else {
      printInOrder(t.leftSubtree());
      System.out.print(t.getRoot() + " ");
      printInOrder(t.rightSubtree());
   }
}
public static void printPreOrder(BinTree t) {
   if (t.isEmpty()) { }
   else {
      System.out.print(t.getRoot() + " ");
      printPreOrder(t.leftSubtree());
      printPreOrder(t.rightSubtree());
   }
}


Activity #2: Family Trees

The relevant files are these:

An instance of the FamilyForest class represents a forest of family trees. (A forest is just a collection of trees.) Among its methods, two are stubbed and are waiting for you to complete them.

The Cousins class is a Java application that constructs a family forest on the basis of the data in a file whose name is provided to it in a command-line argument (or, as jGrasp calls it, a "run argument"). Then it waits for the user to "ask" it to reveal the relationship between two specified nodes in the family forest. Nodes are referred to by natural numbers. One of its methods is left for the student to complete.

The contents of the input.txt file describes the family forest (which has two trees) shown in the left half of the figure below. In the right half is a sample interaction between a user and the Cousins application, which was given the input.txt file as input:

         0                       17
         |                      /  \
         |                     /    \
         1                    18     19
        /|\                  /  \     |
       / | \                /    \    |
      /  |  \             20     21  22
     /   |   \
    /    |    \
   2     3     4
  /     /|      \
 /     / |       \
5     7  8        11
|       / \      / |\
|      /   \    /  | \
6     9    10  12 13  14
                  / \
                 /   \
                15   16
Enter pair of node IDs: 12 4
2-descendant

Enter pair of node IDs: 1 15
4-ancestor

Enter pair of node IDs: 2 16
0-cousins 3 times removed

Enter pair of node IDs: 9 15
2-cousins 1 times removed

Enter pair of node IDs: 7 19
Unrelated

Enter pair of node IDs: 18 18
0-ancestor

Enter pair of node IDs: -1 5
Goodbye.

The relationship (or lack thereof) between two nodes A and B falls into one of four categories:

  1. A and B are unrelated if they have no common ancestor, which is to say that they lie in distinct trees of the family forest.
  2. A is the k-ancestor of B if the path of length k from B towards the root of its tree lands at A. For example, if A is B's grandparent, then A is the 2-ancestor of B. If A and B are the same node, A is the 0-ancestor of B.
  3. A is a k-descendant of B if B is the k-ancestor of A (which is to say that the path of length k from A towards the root of its tree lands at B).
  4. A and B are k-th cousins r times removed if the nearest common ancestor of A and B, call it C, is neither A nor B, and

    where dist(x,y) is the length of the path from x to y (i.e., the number of edges in that path).