Binary Search Trees Nilanjan Banerjee Goal of today’s lecture Learn about Binary Search Trees Discuss the first midterm 2 Binary search trees binary search tree ("BST"): a binary tree where each non-empty node R has the following properties: elements of R's left subtree contain data "less than" R's data, elements of R's right subtree contain data "greater than" R's, R's left and right subtrees are also binary search trees. overall root BSTs store their elements in sorted order, which is helpful for searching/sorting tasks. 55 29 -3 87 42 60 91 3 BST examples Which of the trees shown are legal binary search trees? -5 m g b q k e -1 x 42 5 -7 2 7.2 1.9 11 7 10 18 4 9.6 8.1 8 21.3 20 18 4 Searching a BST Describe an algorithm for searching a binary search tree. Try searching for the value 31, then 6. What is the maximum overall root number of nodes you would need to examine to perform any search? What is the computational Complexity of searching? 18 12 35 4 -2 22 15 7 13 16 19 31 58 40 87 5 Exercise Write a contains method that takes advantage of the BST structure. tree.contains(29) tree.contains(55) tree.contains(63) tree.contains(35) true true false false overall root 55 29 -3 87 42 60 91 6 Exercise solution // Returns whether this BST contains the given integer. public boolean contains(int value) { return contains(overallRoot, value); } private boolean contains(IntTreeNode node, int value) { if (node == null) { return false; // base case: not found here } else if (node.data == value) { return true; // base case: found here } else if (node.data > value) { return contains(node.left, value); } else { // root.data < value return contains(node.right, value); } } 7 Adding to a BST Suppose we want to add new values to the BST below. Where should the value 14 be added? overall root Where should 3 be added? 7? 8 If the tree is empty, where should a new value be added? 5 What is the general algorithm? 2 11 7 10 19 4 25 22 8 Adding exercise Draw what a binary search tree would look like if the following values were added to an initially empty tree in this order: 50 20 75 98 80 31 150 39 23 11 77 50 20 11 75 98 31 23 39 80 150 77 9 Exercise Add a method add to the SearchTree class that adds a given integer value to the BST. Add the new value in the proper place to maintain BST ordering. overall root tree.add(49); 55 29 -3 87 42 60 91 49 10 An incorrect solution // Adds the given value to this BST in sorted order. public void add(int value) { add(overallRoot, value); } private void add(IntTreeNode node, int value) { if (node == null) { node = new IntTreeNode(value); overallRoot } else if (node.data > value) { add(node.left, value); 55 } else if (node.data < value) { add(node.right, value); 29 87 } // else node.data == value, so // it's a duplicate (don't add) -3 42 60 91 } Why doesn't this solution work? 11 The x = change(x) pattern A tangent: Change a point What is the state of the object referred to by p after this code? public static void main(String[] args) { Point p = new Point(1, 2); p x change(p); System.out.println(p); } 1 y 2 public static void change(Point thePoint) { thePoint.x = 3; thePoint.y = 4; } // answer: (3, 4) 13 Change point, version 2 What is the state of the object referred to by p after this code? public static void main(String[] args) { Point p = new Point(1, 2); p x change(p); System.out.println(p); } 1 y 2 public static void change(Point thePoint) { thePoint = new Point(3, 4); } x 3 y 4 // answer: (1, 2) 14 Changing references If a method dereferences a variable (with . ) and modifies the object it refers to, that change will be seen by the caller. public static void change(Point thePoint) { thePoint.x = 3; // affects p thePoint.setY(4); // affects p If a method reassigns a variable to refer to a new object, that change will not affect the variable passed in by the caller. public static void change(Point thePoint) { thePoint = new Point(3, 4); // p unchanged thePoint = null; // p unchanged What if we want to make the variable passed in become null? 15 Change point, version 3 What is the state of the object referred to by p after this code? public static void main(String[] args) { Point p = new Point(1, 2); p x change(p); System.out.println(p); } 1 y 2 public static Point change(Point thePoint) { thePoint = new Point(3, 4); return thePoint; } x 3 y 4 // answer: (1, 2) 16 Change point, version 4 What is the state of the object referred to by p after this code? public static void main(String[] args) { Point p = new Point(1, 2); p x p = change(p); System.out.println(p); } 1 y 2 public static Point change(Point thePoint) { thePoint = new Point(3, 4); return thePoint; } x 3 y 4 // answer: (3, 4) 17 x = change(x); If you want to write a method that can change the object that a variable refers to, you must do three things: 1. 2. 3. pass in the original state of the object to the method return the new (possibly changed) object from the method re-assign the caller's variable to store the returned result p = change(p); // in main public static Point change(Point thePoint) { thePoint = new Point(99, -1); return thePoint; 18 The problem Much like with linked lists, if we just modify what a local variable refers to, it won't change the collection. node 49 private void add(IntTreeNode node, int value) { if (node == null) { overallRoot node = new IntTreeNode(value); } 55 29 -3 87 42 60 91 19 A correct solution // Adds the given value to this BST in sorted order. public void add(int value) { overallRoot = add(overallRoot, value); } private IntTreeNode add(IntTreeNode node, int value) { if (node == null) { node = new IntTreeNode(value); } else if (node.data > value) { overallRoot node.left = add(node.left, value); } else if (node.data < value) { 55 node.right = add(node.right, value); } // else a duplicate; do nothing 29 87 return node; } -3 42 60 91 What happens when node is a leaf? 20 Deletion There are the following possible cases when we delete a node: The node to be deleted has no children. In this case, all we need to do is delete the node. The node to be deleted has only a right subtree. We delete the node and attach the right subtree to the deleted node’s parent. The node to be deleted has only a left subtree. We delete the node and attach the left subtree to the deleted node’s parent. The node to be deleted has two subtrees. It is possible to delete a node from the middle of a tree, but the result tends to create very unbalanced trees. 21 21 Deletion from the middle of a tree Rather than simply delete the node, we try to maintain the existing structure as much as possible by finding data to take the place of the deleted data. This can be done in one of two ways. 22 22 Deletion from the middle of a tree We can find the largest node in the deleted node’s left subtree and move its data to replace the deleted node’s data. We can find the smallest node on the deleted node’s right subtree and move its data to replace the deleted node’s data. Either of these moves preserves the integrity of the binary search tree. 23 23 24 24 (continued) 25 25 27 27 27 27 26 26 Performance of BST methods What is the asymptotic performance of each of the BST methods? Best Case Worst Case Average Case searching insert remove 27 27 Exam Review Topic 1: Java Review Generics in Java, Type Erasure, Virtual Fuction invocation caused by Inheritance Asymptotic Analysis Big Oh notation --- you should be able to look at an implementation and figure it running time in Big Oh L’Hospital Rule Linked List Understand the difference between using an ArrayList and a LinkedList Running time of a LinkedList insertion, deletion, searching an element One problem where you will have to manipulate a linked list Stack and Queues and Adapter Classes 28 28 Exam Trees Definition of a tree One algorithmic question with trees How to traverse a tree Recursive implementation as well as the non-recursive implementation Inorder, Preorder, Postorder, LevelOrder 29 29