INFO1x05 Tutorial 6 Heaps and Priority Queues Exercise 1: 1. How long would it take to remove the log n smallest elements from a heap that contains n entries, using the operation? 2. Suppose you label each node v of a binary tree T with a key equal to the preorder rank of v. Under what circumstances is T a heap? 3. What is the output from the following sequence of priority queue ADT methods? (Assume the operation prints out the removed element.) insert(5, A) insert(4, B) insert(7, I) insert(1, D) insert(3, J) insert(6, L) insert(8, G), insert(2, H) (a) Each removemin call runs in O (log n), so log n calls would run on the order of O ( log 2 n ). (b) Always, as the parent node will always have a smaller value than its children. Remember, a heap makes no constraints as to the ordering of siblings/cousins etc. (c) (1,D), (3, J), (4,B), (5,A), (2,H), (6,L). 1
Exercise 2: In Java, the PriorityQueue() implementation implements a min-heap type priority queue. Although it is technically correct to use a reverse comparator with the PriorityQueue, so that objects are inserted into the heap in reverse order, it can be confusing to get back the element with the maximal value every time we call a method called. Write a short adaptor class which wraps around the PriorityQueue() class and constructs a max-heap, with methods like RemoveMax() to access elements. See git repo tutes/w06/soln. Exercise 3: 1. Illustrate the execution of the selection-sort algorithm on the following input sequence: 22,, 36, 44, 10, 3, 9, 13, 29, 25 22 36 44 10 3 9 13 29 25 3 36 44 10 22 9 13 29 25 3 9 36 44 10 22 13 29 25 3 9 10 44 36 22 13 29 25 3 9 10 13 36 22 44 29 25 3 9 10 13 22 36 44 29 25 3 9 10 13 22 36 44 29 25 3 9 10 13 22 25 44 29 36 3 9 10 13 22 25 29 44 36 3 9 10 13 22 25 29 36 44 2. Give an example of a worst-case sequence with n elements for insertion-sort, and show that insertion-sort runs in Ω(n 2 ) time on such a sequence. A worst-case sequence for insertion sort would be one that is in descending order of keys, e.g., 44 36 29 25 22 13 10 9 3. With this sequence, each element will first be moved to the front and then moved back in the sequence incrementally, as every remaining is processed. Thus, each element will be moved n times. For n elements, this means at a total of n 2 times, which implies Ω(n 2 ) time overall. Data Structures Page 2 of 7
Exercise 4: (INFO05) Show how to implement the stack ADT using only a priority queue and one additional integer instance variable. Then, implement a class MyStack in java, using a wrapper around the PriorityQueue class. Your class should be able to store String objects. A skeleton is provided below: Note: Keep in mind that the Java priority queue is a min-heap. 1 import java.util.priorityqueue; 2 3 public class MyStack { 4 public MyStack() { 5 // Your code goes here 6 } 7 8 public void push(string s) { 9 // Your code goes here 12 public String pop() { 13 // Your code goes here 16 public int size() { 17 // Your code goes here 20 public boolean isempty() { 21 // Your code goes here 23 } Hint: You may find the following class helpful: 1 public class KeyValue <E> 2 implements Comparable<KeyValue<E> > { 3 4 private Integer key; 5 private E value; 6 7 public KeyValue(int key, E value) { 8 this.key = key; 9 this.value = value; 12 public Integer getkey() { 13 return key; 16 public E getvalue() { 17 return value; Data Structures Page 3 of 7
20 public int compareto(keyvalue<e> o) { 21 return key.compareto(o.key); 23 24 } Extension: Modify your class so it can store arbitrary data types. Maintain a variable m initialized to 0. On a push operation for element e, call insert(m, e) and decrement m. On a pop operation, call remove and increment m. Programming Solution in repo. Exercise 5: (INFO05) Show how to implement the (standard) queue ADT using only a priority queue and one additional integer instance variable. Then, implement a class MyQueue in java, using a wrapper around the PriorityQueue class. Your class should be able to store String objects. A skeleton is provided below: Note: Keep in mind that the Java priority queue is a min-heap. 1 import java.util.priorityqueue; 2 3 public class MyQueue { 4 public MyQueue() { 5 // Your code goes here 6 } 7 8 public void enqueue(string s) { 9 // Your code goes here 12 public String dequeue() { 13 // Your code goes here 16 public int size() { 17 // Your code goes here 20 public boolean isempty() { 21 // Your code goes here 23 } Data Structures Page 4 of 7
Hint: You may find the following class helpful: 1 public class KeyValue <E> 2 implements Comparable<KeyValue<E> > { 3 4 private Integer key; 5 private E value; 6 7 public KeyValue(int key, E value) { 8 this.key = key; 9 this.value = value; 12 public Integer getkey() { 13 return key; 16 public E getvalue() { 17 return value; 20 public int compareto(keyvalue<e> o) { 21 return key.compareto(o.key); 23 24 } Extension: Modify your class so it can store arbitrary data types. Maintain a maxkey variable initialized to 0. On an enqueue operation for element e, call insertitem(maxkey, e) and increment maxkey. On a dequeue operation, call removeminelement and decrement maxkey. Programming Solution in Repo. Exercise 6: (INFO05) Given a heap T and a key k, give an algorithm to compute all the entries in T with key less than or equal to k. For example, the heap show in Figure?? and query k = 7, the algorithm should report the entries with keys 2, 4, 5, 6, and 7 (but not necessarily in this order). Your algorithm should run in time proportional to the number of entries returned. Data Structures Page 5 of 7
(2, C) (5, A) (4, C) (, K) (9, F) (7, Q) (6, Z) (16, X) (25, J) (14, E) (12, H) (, S) (8, W) (20, B) (10, L) Figure 1: Heap T Starting at the root of the tree, recursively search the left and right subtrees if the root of the subtree has a key value less than k. This algorithm takes O(k) time, because there is no node in T storing a key larger than k that has a descendent storing a key less than k. Exercise 7: (INFO05) Develop an algorithm that computes the kth smallest element of a set of n distinct integers in O(n + k log n) time. Construct a heap, which takes O(n) time. Then call removemin k times, which takes O(k log n) time. Exercise 8: (INFO05) An online computer system for trading stock need to process orders of the form buy 100 shares at $x each or sell 100 shares at $y each. A buy order for $x can only be processed if there is an existing sell order with price $y such that y x. Likewise, a sell order for $y can only be processed if there is an existing buy order with price $x such that y x. If a buy or sell order is entered but cannot be processed, it must be stored until an order is entered which allows it to be processed. Describe a scheme that allows for buy and sell orders to be entered in O(log n) time, independent of whether or not they can be immediately processed. Data Structures Page 6 of 7
Create two heaps, one for sell orders, the other for buy orders. We need to store in each node both the quantity and price, with the price as the key. When an order comes in, keep popping items off the corresponding priority queue, until a large enough quantity has been removed, subject to the constraint. On failure, add the popped items back onto the priority queue and the other order onto the other queue. On average we would expect this algorithm to run in O (log n) time, however in the worst case, it will take O (n log n) time, as to fulfil an order we may have to empty the queue. Exercise 9: (INFO05) Write a comparator for nonnegative integers that determines order based on the number of 1 s in each integer s binary expansion, so that i < j if the number of 1 s in the binary representation of i is less than the number of 1 s in the binary representation of j. 1 import java.util.comparator; 2 public class integercomparator implements Comparator { 3 private int countbits(object a) { 4 if( a == null ) { 5 throw new RuntimeException("Null Argument"); 6 } 7 try{ 8 int numones = 0; 9 int tmp = ((Integer) a).intvalue(); 10 while( tmp!= 0 ) { int bit = tmp & 1; 12 if( bit == 1 ) 13 numones++; 14 tmp = tmp >> 1; } 16 return numones; 17 } 18 catch( ClassCastException e ) { throw new RuntimeException("Argument is not an Integer"); 20 } 21 } 22 public int compare(object a, Object b) { 23 int vala = countbits( a ); 24 int valb = countbits( b ); 25 return ( vala - valb ); 26 } 27 } Data Structures Page 7 of 7