CSC153, Class 49: Priority Queues, Heaps, and Heapsort Overview: * Priority queues * Using priority queues for sorting * Simple implementations + Array or simple list + Sorted list * Trees: Divide-and-conquer data structures * Heaps: Trees for priority queues * Implementing heaps Notes: * CS151 presentations at 2:15. * Food! (Including some that's good for you.) * Dr. Freda Rebelsky visits. * Exam 4 ready. * Read Bailey. * The optional final is in-class 3 hours + Yes, hyou'll get your other exams back first + Yes, it's on Scheme and Java + Yes, you can take it for "fun", but you should then seek assistance from mental health, "you damn freaks" (EC) ---------------------------------------- Review: Linear Structures * It's like a list, except ... It's a bunch of elements linked together * Add, Destructive "Move on To Next" (get), isEmpty * What determines what you get when you call get? + Each kind of linear structure has a policy * Stacks: LIFO * Queues: FIFO * Microsoft: GIGO * Priority queues: The thing with the highest priority is returned by get How do we determine the priority? * Requre each element to have a priority field * "Binary Priority Predicate" * Unary Priortizer Why are priority queues useful? * Some things in life are more important than others For example, you might use a priority queue for admissions at Grinnell. * Priorities change! (An argument for predicates or prioritizers) * Balance between queues and stacks If you hand me an empty priority queue, I can sort really easily. * Choose a prioritizer or predicate that indicates the order you want. * Add all the elements * Remove all the elements in order Running time? * O(n) "No! I agree." But I told you comparison-based sorting algorithms are always at least O(nlogn). * Sam is lying * Your analysis is wrong * Both * Adding all the elements O(n*cost-of-addition) * Removing all the elements O(n*cost-of-deletion) It only takes O(1) steps to add to a regular queue. Can we make it take O(1) steps to add to a priority queue? * Sure: Stick it at the end. To get: * Find the thing with the highest priority in the list/array? O(n) If we choose this implementation, the running time of "Priority Queue Sort" is O(n^2) Alternative implementation: Store them in sorted order To get: * O(1) To add: * Claim: Binary search to find place and insert there + Linked lists: O(n) to find + Arrays: O(n) to "insert" 1 + 2 + ... + n-1 + n = n*(n+1)/2 in O(n^2) Clever idea: Apply the "divide and conquer" approach to data structure design Remember trees from before break (yeah, sure) A tree is either null or A triplet of two subtrees and a value Terminology: * Left and right subtrees also called left and right children * Root of a tree is the triplet * Leaf: Tree with only null subtrees * Depth: The longest number of steps from root to leaf * Complete: All nodes on the same "level" have either all children non-null or all children null + Parse this the correct way * Binary public class BinaryTreeNode { Object value; BinaryTreeNode left; BinaryTreeNode right; } // class BinaryTreeNode Complete binary trees are not very deep: O(log_2(n)) Tree with 1 level: 1 Tree with 2 levels: 3 Tree with 3 levels: 7 Tree with 4 levels: 15 Tree with k levels: 2^k - 1 If you can do operations that are O(depth), those operations are relatively fast. Interesting data structure based on binary trees, usable for priority queues: * Heaps are binary trees that + are nearly complete: all levels except the last are complete; last level is "shoved to left" + have the "heap property": the value in the root has a priority at least as high as the priorities of the roots of the children and the children are heaps" To peek at the the highest priority element in a heap: * Grab the thing at the root To delete the highest priority element in a heap: * Remove the value in the root * Move the last value on the last level to the root * "Swap down" To add a new element to a heap: * Add to the last level * "Swap up" How do you find the "end of the last level"? Cool trick: Use an array for the heap