Heaps, stacks, queues Dan S. Wallach and Mack Joyner, Rice University Copyright 216 Dan Wallach, All Rights Reserved
Where was Prof. Wallach on Tuesday?
Two hours of scintillating Congressional testimony: https://www.youtube.com/watch?v=iru9zuff9a
At the end of the semester, if we have time, we ll have a lecture on computer security & electronic voting. Two hours of scintillating Congressional testimony: https://www.youtube.com/watch?v=iru9zuff9a
Preliminaries: queues vs. stacks Stack: last-in-first-out (LIFO) Our IList classes work like this. Queue: first-in-first-out (FIFO) You implemented this last week. Functional vs. mutating? Straightforward to do it either way.
How do you implement a mutating queue? Option 1: doubly-linked list (java.util.linkedlist) Every node has pointers to next and previous nodes Sentinel node to deal with empty-list case O(1) insert and removal Possible to add and remove from either end (= Deque or Dequeue) Option 2: array (java.util.arraydeque) Tricky: requires growing the array, tracking start/end, wraparound O(1) insert and removal (amortized: sometimes requires an O(n) copy)
How about a functional queue? Option 1: use two lists ( inbox and outbox ) You built this last week. Constant amortized time. Option 2: use a tree (not recommended) You ll notice that our trees have a getmin method. All operations are O(log n)
So what s a priority queue? Priority queues are typically implemented via mutation. getmin() returns the smallest value and removes it at the same time. public interface IPriorityQueue<T> { T getmin(); void insert(t val); int size(); boolean empty(); }
Binary heaps: efficient priority queues Storage happens in an array (or java.util.arraylist) Map a tree into the array. No pointers, just math on array indices. leftchild(i) = 2i + 1 rightchild(i) = 2i + 2 parent(i) = (i-1)/2 4 2 Note: integer arithmetic 9 A tree like this is called complete. Heap values Array index 2 4 9
Binary heaps: data definition The heap property : A parent s value is less than (or equal to) its children s values. Ergo: The minimum value is in the root. And that s the zeroth element. 4 2 9 A tree like this is called complete. Heap values Array index 2 4 9
Binary heaps: inserting a new value First, go to the next available slot (here, #8) Work upwards, swapping to create the heap property 2 insert() 4 9
Binary heaps: inserting a new value First, go to the next available slot (here, #8) Work upwards, swapping to create the heap property 2 insert() 4 9 8
Binary heaps: inserting a new value First, go to the next available slot (here, #8) Work upwards, swapping to create the heap property 2 insert() 4 9 8
Binary heaps: inserting a new value First, go to the next available slot (here, #8) Work upwards, swapping to create the heap property 2 insert() 4 9 8
Binary heaps: inserting a new value First, go to the next available slot (here, #8) Work upwards, swapping to create the heap property 2 insert() 4 9 8
Binary heaps: inserting a new value First, go to the next available slot (here, #8) Work upwards, swapping to create the heap property 2 insert() 4 9 8
Binary heaps: inserting a new value First, go to the next available slot (here, #8) Work upwards, swapping to create the heap property 2 insert() 4 9 8
Binary heaps: inserting a new value First, go to the next available slot (here, #8) Work upwards, swapping to create the heap property 2 insert() Insertion cost: O(log n) Stable, predictable. 4 9 8
Binary heaps: removing the min value The answer is right on top, so that s easy But what about the children? 2 First, move the last child to the top. 4 9 8
Binary heaps: removing the min value The answer is right on top, so that s easy But what about the children? 2 First, move the last child to the top. 4 9 8
Binary heaps: removing the min value The answer is right on top, so that s easy But what about the children? Now recursively work down Reestablish the heap property. Use the smallest value. If equal, either is fine. 4 9
Binary heaps: removing the min value The answer is right on top, so that s easy But what about the children? Now recursively work down Reestablish the heap property. Use the smallest value. If equal, either is fine. 4 9
Binary heaps: removing the min value The answer is right on top, so that s easy But what about the children? Now recursively work down Reestablish the heap property. Use the smallest value. If equal, either is fine. 4 9
Binary heaps: removing the min value The answer is right on top, so that s easy But what about the children? Now recursively work down Reestablish the heap property. Use the smallest value. If equal, either is fine. 4 9
Binary heaps: removing the min value The answer is right on top, so that s easy But what about the children? Now recursively work down Reestablish the heap property. 4 Use the smallest value. If equal, either is fine. 9
Binary heaps: removing the min value The answer is right on top, so that s easy But what about the children? Now recursively work down Reestablish the heap property. 4 Use the smallest value. If equal, either is fine. 9
Binary heaps: removing the min value The answer is right on top, so that s easy But what about the children? Now recursively work down Reestablish the heap property. 4 Use the smallest value. If equal, either is fine. 9 Total cost: O(log n)
Using arrays is a serious win Compact memory usage (no left/right pointers) Navigating up or down is easy O(log n) operations aren t just expected case A heap is always a complete tree, so it s always O(log n) ArrayList vs. arrays ArrayList will automatically allocate bigger arrays (internally) and copy.
Performance numbers FIFO queues (functional) ListQueue : 1 inserts, 1 fetches:.1 μs per insert TreapQueue : 1 inserts, 1 fetches:.8 μs per insert FIFO queues (mutating) LinkedList : 1 inserts, 1 fetches:.2 μs per insert ArrayDeque : 1 inserts, 1 fetches:.18 μs per insert Priority queues (mutating) BinaryHeap : 1 inserts, 1 fetches:.99 μs per insert PriorityQueue: 1 inserts, 1 fetches:.61 μs per insert
Performance numbers FIFO queues (functional) ListQueue : 1 inserts, 1 fetches:.1 μs per insert TreapQueue : 1 inserts, 1 fetches:.8 μs per insert FIFO queues (mutating) LinkedList : 1 inserts, 1 fetches:.2 μs per insert ArrayDeque : 1 inserts, 1 fetches:.18 μs per insert Priority queues (mutating) BinaryHeap : 1 inserts, 1 fetches:.99 μs per insert PriorityQueue: 1 inserts, 1 fetches:.61 μs per insert Mutation is winning big, this time...
Live coding Q&A for project 4 Advice for debugging Build your valid() method first, then use it to test. Take advantage of printing your treaps. Use tostringhelper().