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