Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
CS II: Data Structures Discussion worksheet: Week 9 Binary Search Trees, Balanced Trees Part 1 1. Draw out a Binary Search Tree of the following nodes in this order, starting with 44 as the root: 44, 17, 88, 8, 32, 65, 28, 21, 29, 54, 97, 82, 76, 93, 80 44 17 88 2. Write out a recursive method that searches for a number in a binary search tree. Lastly, if the number is found, return the node, else return null. private class Node { private Key key; private Value val; private Node left, right; private int size; // // // // sorted by key associated data left and right subtrees number of nodes in subtree } private Node search(int num, Node node){ if(node == null){ return null; } else if(node.val == num){ return node; } else if(node.val < num){ return search(num, node.left); } else{ return search(num, node.right); } } 3. Using your search method above, write a list of the recursive calls using the tree from Question 1. You are to search for 93. In place of the second argument, Node node, write the current value you are on. The first call is search(93, 44) because 44 is the root node. search(93,44); search(93,88); search(93,97); search(93,93); 4. Reflection: What is the worst-case running time of searching this tree? O(h) which is the height of the tree If the tree is balanced, then you are search for an element in O(log n) time which is the height of the tree h. If the tree isn’t balanced, then searching for an element at worst takes linear time. Part 2 5. Now write an algorithm that inserts the element in the tree like you illustrated above in question 1. Use the BST class below and fill in the put method. public class BST<Key extends Comparable<Key>, Value> { private Node root; // root of BST private class Node { private Key key; private Value val; private Node left, right; private int size; // // // // sorted by key associated data left and right subtrees number of nodes in subtree public Node(Key key, Value val, int size) { this.key = key; this.val = val; this.size = size; } } private Node put(Node x, Key key, Value val) { if (x == null) return new Node(key, val, 1); int cmp = key.compareTo(x.key); if(cmp < 0){ x.left = put(x.left, key, val); } else if(cmp > 0){ x.right = put(x.right, key, val); } else{ x.val = val; } x.size = 1 + size(x.left) + size(x.right); return x; } } Part 3 6. Do the same as Part 1 Question 1 with this data set: 150, 140, 50, 30, 12, 9, 6 7. Reflection: What is the worst case running time of insertion and searching for an element in this tree? O(n), because this tree isn’t balance. 8. Write a method that would create a balance binary tree from a sorted array. Below is a public method, as well as a private method to use as a recursive helper function. public Node sortedArrayToBST(int arr[]) { return sortedArrayToBST(arr, 0, arr.length-1); } private Node sortedArrayToBST(int arr[], int start, int end) { if (start > end) return null; // same as (start+end)/2, avoids overflow. int mid = start + (end - start) / 2; Node node = new Node(arr[mid]); node.left = sortedArrayToBST(arr, start, mid-1); node.right = sortedArrayToBST(arr, mid+1, end); return node; } 9. Reflection: For a balanced binary search tree, what is the worst case running time of insert() and search() for an element in this tree? O(log n) because now you can drop half of the input for each method call as long as the tree is balanced. Part 4 10. Next implement remove for our Binary Search Tree, you do not have to leave the tree balanced: The String key is the value of the node that we are trying to remove. The Node pos is holder/pointer node for your recursive calls. public void remove (String key, Node pos) { if (pos == null) return; /* Cycle through until you find the node to delete */ if (key.compareTo(pos.key) < 0){ remove (key, pos.left); } else if (key.compareTo(pos.key) > 0){ remove (key, pos.right); } else { /* We found the node to delete */ //Case 1: Node to delete has left and right children if (pos.left != null && pos.right != null) { //Note, it is good coding practice to put these helper methods in a separate method. //At most, your method shouldn't be over 10 or so statements, you should refactor to make //methods smaller or legible for other users. /* pos has two children */ Node maxFromLeft = pos.left; while(maxFromLeft.right != null){ maxFromLeft = temp.right; } //"Replacing " pos.key " with " maxFromLeft.key pos.key = maxFromLeft.key; //Remove the node we just swapped into the place of the node to delete remove (maxFromLeft.key, pos.left); } //Case 2: Node to delete has left children else if(pos.left != null) { /* node pointed by pos has at most one child */ Node trash = pos; //"Promoting " pos.left.key " to replace " pos.key pos = pos.left; trash = null; } //Case 3: Node to delete has right children else if(pos.right != null) { /* node pointed by pos has at most one child */ Node trash = pos; /* "Promoting " pos.right.key" to replace " pos.key */ pos = pos.rightChild; trash = null; } //Case 4: Node to delete is the root else { pos = null; } } }