Lecture 13: AVL Trees and Binary Heaps
Total Page:16
File Type:pdf, Size:1020Kb
Data Structures Brett Bernstein Lecture 13: AVL Trees and Binary Heaps Review Exercises 1.( ??) Interview question: Given an array show how to shue it randomly so that any possible reordering is equally likely. static void shue(int[] arr) 2. Write a function that given the root of a binary search tree returns the node with the largest value. public static BSTNode<Integer> getLargest(BSTNode<Integer> root) 3. Explain how you would use a binary search tree to implement the Map ADT. We have included it below to remind you. Map.java //Stores a mapping of keys to values public interface Map<K,V> { //Adds key to the map with the associated value. If key already //exists, the associated value is replaced. void put(K key, V value); //Gets the value for the given key, or null if it isn't found. V get(K key); //Returns true if the key is in the map, or false otherwise. boolean containsKey(K key); //Removes the key from the map void remove(K key); //Number of keys in the map int size(); } What requirements must be placed on the Map? 4. Consider the following binary search tree. 10 5 15 1 12 18 16 17 1 Perform the following operations in order. (a) Remove 15. (b) Remove 10. (c) Add 13. (d) Add 8. 5. Suppose we begin with an empty BST. What order of add operations will yield the tallest possible tree? Review Solutions 1. One method (popular in programs like Excel) is to generate a random double corre- sponding to each element of the array, and then sort the array by the corresponding doubles. Here is a dierent method that avoids sorting (used by Collections.shue). RandomShue.java import java.util.Random; public class RandomShue { static void swap(int[] arr, int i, int j) { int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } //Iterative implementation public static void shue(int[] arr) { Random ran = new Random(); for (int i = arr.length−1; i >= 1; −−i) swap(arr,i,ran.nextInt(i+1)); } //Recursive implementation public static void shueRec(int[] arr) { sRHelp(arr, arr.length, new Random()); } public static void sRHelp(int[] arr, int len, Random ran) { if (len <= 1) return; swap(arr, len−1, ran.nextInt(len)); sRHelp(arr,len−1,ran); } } 2 Above we give an iterative and a recursive implementation. We rst randomly choose one of the elements and swap it into the nal position. Then we repeat the process on the rst n − 1 elements (i.e., randomly choose last element, and then randomly shue rst n − 1 elements). 2. public static BSTNode<Integer> getLargest(BSTNode<Integer> root) { while (root.getRight() != null) root = root.getRight(); return root; } 3. We require the keys of the Map to be Comparable or a Comparator to be provided. In each node instead of simply storing a value, store a key-value pair (i.e., an entry). The BST will be ordered by the keys. Here all operations above will be Θ(h) in the worst case (we don't have containsValue above which would always be Θ(n)). In a moment, we will show how to achieve Θ(lg n) height trees which gives an ecient Map implementation without needing a hash function (but we need ordered keys). 4. (a) 10 5 16 1 12 18 17 (b) 12 5 16 1 18 17 (c) 12 5 16 131 18 17 (d) 3 12 5 16 1318 18 17 5. Ascending or descending order (i.e., sorted or reverse sorted). Data Structure: AVL Tree We have learned how to store values in a BST data structure that supports adding, removal, and searching in time Θ(h), where h is the height of the tree. We have also seen that in the worst case, the height can be Θ(n), the size of the tree. If we can keep the tree fairly balanced, then we can reduce the height to Θ(lg n) and obtain a fairly ecient data structure. To maintain a balanced structure we will use a technique invented by Adelson-Velskii and Landis (hence the name AVL tree). The idea is to keep a counter in every node (called a balance factor) that measures the dierence between the heights of the left and right subtrees (right minus left). We will add the following added constraint on our BST No balance factor will be greater than 1 or less than -1. Any BST that satises this constraint will have Θ(lg n) height. Every time we add or remove a node we may violate this constraint. To return the tree to balance we will employ a technique called a rotation. Consider the following AVL tree: 10 +1 5 15 -1 +1 1 12 20 0 0 -1 17 0 Each node has the value and balance factor in it. Now suppose we add 16 (just as we would in a BST). 4 10 +2 5 15 -1 +2 1 12 20 0 0 -2 17 -1 16 0 As you can see, the tree now violates our constraints on the balance factors. To remedy the issue, we nd the closest (lowest) ancestor of the newly added node that is out of balance. In this case, it would be the node containing the 20. We then perform a rotation so that 17 takes the place of 20, and 20 becomes the right child of 17. The resulting tree is 10 +1 5 15 -1 +1 1 12 17 0 0 0 16 20 0 0 Now the tree satises the constraint again. Let's generalize this example to all possible ways adding a node can imbalance the tree. First notice that if adding a value will cause a node to violate its balance factor constraint, then it must have been −1 or +1 already, since adding a single node can add at most 1 to the height of any subtree. Let's assume a node currently has balance factor −1 and some value X. We will model the possible ways that the node containing X will be the lowest node that violates the balance factor constraint (by adding values). 5 X -1 Y 0 C k k A B k Above Y < X and all of the labeled subtrees have the same height k ≥ 0. The subtree rooted at X has height k + 1. We rst handle the case that a node is added to subtree A that increases its height. X -2 Y -1 Z C k B k A1 A2 Here we assumed the value added was smaller than Y . Note that the subtree rooted at X now has height k + 2. We then zoom in on the subtree A by drawing its root Z and subtrees A1 and A2. The possible heights of A1;A2 are (this will not eect our course of action though): 1. If k = 0 then A1;A2 are both empty. Z has a balance factor of 0 2. If k > 0 and the new value is smaller than Z then A1 has height k and A2 has height k − 1. Z has a balance factor of −1. 3. If k > 0 and the new value is greater than Z then A1 has height k − 1 and A2 has height k. Z has a balance factor of +1. To x this we perform a rotation that puts Y where X is: 6 Y 0 ZX 0 A1 A2 BC k The balance constraints are no longer violated. Note that the subtree rooted at Y has height k + 1, the same as the subtree rooted at X before a value was added. Thus all nodes above Y in the tree are now balanced as well. This is the so called left-left case since Z is the left child of Y which is the left child of X. The other left-right case occurs when we add a value that is larger than Y to our original tree (the picture with A, B, and C) above. X -2 Y +1 W C k k A B1 B2 Here we have zoomed in on the subtree B. We have similar cases as above that determine the heights of B1;B2. Here we perform a rotation that puts W in place of Y : X -2 W Y C k B2 k A B1 This gives us a case like the left-left situation. Thus we perform a second rotation as above putting W in place of X: 7 W 0 YX k A B1 B2 C k Again we have restored balance and the resulting tree has height k + 1. Thus all ancestors of W are balanced too. Using the operations above and their reections (right-right and right-left cases) we can enforce the balance constraints on every add operation. The TreeMap and TreeSet in Java use a related data structure called a red-black tree that uses a slightly dierent constraint for balance, but also uses rotations to enforce the constraint. AVL Tree Exercises 1. Consider the following BST. 10 5 15 6 12 (a) Add balance factors to all of the nodes. (b) Show what happens when we add the node 13 (treating the tree as an AVL tree). (c) Next add 7 to the tree (treating the tree as an AVL tree). (d)( ?) Next delete 5, 7, and 6 from the tree. Make sure to remedy any violated balance constraints. 2. Give a simple Θ(n lg n) sorting algorithm assuming you have access to an AVL Tree data structure. 3.( ??) The AVL Tree deletion algorithm is similar to the addition algorithm, but can cause as many as Θ(h) rotations to occur where h is the height of the tree.