Lab 11 Binary Search Trees Goals After completing this lab, you should be able to: Describe and use different binary tree properties such as height, full, complete, and balanced. Produce preorder, inorder, and postorder traversals of a binary search tree. Understand how to implement a binary search tree using a reference-based implementation. Be able to use the Binary Search Tree ADT to organize elements in sorted manner, and to write methods for a class implementing the BST ADT. Binary Tree Properties Consider the following binary search tree. Answer each of the questions that follow. How many leaves does this tree have? _________________________________ How many nodes are in the right subtree of the root's left child? _____________ What is the height of this tree? _______________________________________ What is the maximum number of nodes this tree can have at this height? ______ Is the tree full? Explain. ____________________________________________ Is the tree complete? Explain. ________________________________________ Is the tree balanced? Explain. ________________________________________ Building a Binary Search Tree Create a program BSTTest that declares an object bst of type BinarySearchTree. Add lines of code to your program that would create the tree as shown above. You need to insert each letter one by one. For example, to add the root node you would use the line that follows. bst.add('M'); The order you add the items does matter to a certain extent. For example, you would have to add 'M' before you add 'J' or you would have a different tree. Print out your tree once it's built using the print method. Using java.util.TreeSet Add a block of code that does the same things as described in the previous section, using TreeSet<Character> and compare different styles for tree presentation with the two tree classes. Implement a toString Method Now, let's implement a toString method for the BinarySearchTree class such that it can present a BST object in the standard Java style. Instead of printing the contents along the way as does the print() method, this method will append contents to a string and return it to the client code. The standard Java string representation of collections is defined in the AbstractCollection class, as follows: The string representation consists of a list of the collection's elements in the order they are returned by its iterator, enclosed in square brackets ("[]"). Adjacent elements are separated by the characters ", " (comma and space). Elements are converted to strings as by String.valueOf(Object). After compiling the BinarySearchTree class, execute the BSTTree class again to see the new output. Both lines should read [D, F, J, L, M, S, T, W, Z]. Traversal Practices The print() method traverses a BST in the in-order manner, so as to display contents stored in the tree in the ascending order. Other frequently used traversal orders include pre- and post-orders. Practice both preorder and postorder traversal of our tree, and write the results below. If you're not sure if your answer is correct, let me know and I'll be glad to check it for you. Rename the print() method as printInOrder(). Copy and modify its code to implement two more methods, printPreOrder()and printPostOrder(). Test them with our tree and compare results with what you got from above. Implement a size Method Next, let's implement a size method for the BinarySearchTree class. This public method will need to invoke a recursive private countNodes method of its inner class BinarySearchTreeNode. You may use the following base/recursive cases in structuring your countNodes method. - A node with no child: return 1 - A node with only a left/right subtree: return 1 + count of nodes in left/right subtree (two cases) - Otherwise (i.e., a node w/ 2 subtrees): return 1 + two counts one for each subtree Deletion Practice Add a line to the BSTTest program to delete the root of this tree (the M element). Next, re-print out a preorder traversal of this tree. Before compiling and testing your program, draw the new tree below that would result once the root is deleted. Deliverables Submit your code and the complete lab worksheet by Tuesday, November 18, at beginning of class. 2 public String toString() { StringBuilder returnValue = new StringBuilder(); //inOrderTraversal(this, returnValue); inorderTraversal(returnValue); return "[" + returnValue.toString() + "]"; } private void inOrderTraversal(BinaryTreeNode curNode, StringBuilder st) { if (curNode.left != null) inOrderTraversal(curNode.left, st) ; st.append((st.toString().equals("")?"":", ") + curNode.data); if (curNode.right != null) inOrderTraversal(curNode.right, st) ; } private void inorderTraversal(StringBuilder st) { if (left != null) left.inorderTraversal(st) ; st.append((st.toString().equals("")?"":", ") + data); if (right != null) right.inorderTraversal(st) ; } 3