Lec 05 - Priority Queue
Definition
In a priority queue, each element has a "priority" and an element with higher priority is served before an element with lower priority.
And in Java, the priority queue is implemented using Binary Min Heap. So, here we will introduce the definition of binary heap also.
Binary Max Heap
A Binary (Max) Heap is a complete binary tree that maintains the Max Heap property.
Complete Binary Tree: Every level in the binary tree, except possibly the last/lowest level, is completely filled, and all vertices in the last level are as far left as possible
Binary Heap property: It has two versions, max and min.
Binary Max Heap Property: The value of a vertex — except the leaf/leaves — must be greater than (or equal to) the value of its one (or two) child(ren).
Binary Min Heap Property: Just the opposite of the above. The value of a vertex — except the leaf/leaves — must be less than (or equal to) the value of its one (or two) child(ren).
Below is an example of a binary max heap from visualgo. And remember this general shape of a complete binary tree as it will be useful when we analyze the basic operation inside ths binary max heap.

Additional Information
Height: the height of a tree is the number of edges from the top-most node to the farthest node in a subtree. For example, in the figure above, the height of this complete binary tree is 3.
Basic Manipulation
A complete binary tree can be stored efficiently as a compact array A as there is no gap between vertices of a complete binary tree/elements of a compact array. (Go back to visualgo to visualize this process).
This way, we can implement basic binary tree traversal operations with simple index manipulations (with help of bit shift manipulation):
parent(i) = i>>1, indexidivided by 2 (integer division),left(i) = i<<1, indeximultiplied by 2,right(i) = (i<<1)+1, indeximultiplied by 2 and added by 1.
Insert
Insertion of a new item v into a Binary Max Heap can only be done at the last index N plus 1 to maintain the compact array. Why?
This is to maintain the complete binary tree property.
However, the Max Heap property may still be violated. This operation then fixes Max Heap property from the insertion point upwards (if necessary) and stop when there is no more Max Heap property violation. (See the visualization on visualgo to understand it better)
ExtractMax
The method returns and deletes the root vertex, then replace the root with the last index N. This is also to maintain the complete binary tree property.
But after the replacement, it will very likely violates the Max Heap property. This operation then fixes Binary Max Heap property from the root downwards by comparing the current value with the its child/the larger of its two children (if necessary). (Again, see the visualization on visualgo to understand it better)
Create
To create a binary max heap, one trivial way is to call the Insert N times. Thus, its time complexity will be . However, to make it faster, there is the second way to create a binary max heap,
insert each vertex sequentially, don't care about the max heap property
ignore all the bottom leaves, and start fixing the max heap property (by calling
shiftDown()) from the second-last level of vertices, one-by-one and do this all the way until the root vertex.
Analysis of Create
The height of a full binary tree of size is .
The cost to run
shiftDown(i)operation is not the gross upper bound , but where is the height of the subtree rooted at . And thus, we can write , where is a constant.There are vertices at height in a full binary tree.
On the example full binary tree above with and ,

There are, vertices at height (the bottom level).
After knowing the above three points and using the idea to start from all the way to the root, we can derive the formula to calculate the analysis as follows,
Equation Explanation
From formula 2 to 3, it suffices to calculate .
From formula 3 to 4, it uses the formula that , and here we just let .
Take away from two creates
So, the take away from these two different creates is that,
If our starting point is different, we may get different results.
In this case, if we start fixing the binary max heap property from the root and down until the height = 1 level of vertices, we get complexity. But if we start fixing the binary max heap property from the height = 1 level of vertices and up until the root, we get complexity. Thus, try changing start point when solving some problems☺️.
Update
To update the priority of an existing value that is already inserted into a Binary (Max) Heap, if the index i of the value is known, we can do the following simple strategy:
Simply update
A[i] = newvand thencall both
shiftUp(i)andshiftDown(i).
Delete
To delete an existing value that is already inserted into a Binary Max Heap and we already know the index of the value to be deleted, we can just
update
A[i]=A[1]+1(a larger number greater than the current root),call
shiftUp(i)(technically,UpdateKey(i, A[1]+1)))then call
ExtractMax()once to remove it.
HeapSort
HeapSort is just simply calling the ExtractMax operation N times. Thus, its time complexity is obviously . (See the visualization on visualgo!)
One advantage of Heapsort is that we can use it to achieve partial sort! (Its real world application includes the searching result you get from Google). And below is an application from LeetCode 😂
For the explanation, please see from here!
More Binary Heap
This part mainly comes from the Week 6's tutorial content.
Number of comparisons
The orginal question is,
What is the minimum and maximum number of comparisons between Binary Heap elements required to construct a Binary (Max) Heap of arbitrary n elements using the
Create(array)?
The minimum case is when everything is in order, the number of comparions is just the number of edges in the bianry tree.
The maximum case needs manual computation starting from the second-last layer, but the idea is "try to bubble/shift every node to the bottom layer"
Find the all numbers greater than k in Binary Max Heap in
This problem is a bit different from the leetcode one, as it explicitly specifies that the algorithm should be within time. And it needs to print out all the vertices that are greater than k.
To solve it, we need to use the recursive/wishful thinking (we have learned in CS1010 or maybe CS1101S). So, we can break a bigger Binary Heap into three parts,
The left Binary Heap,
The root,
The right Binary Heap
In each breakdown, we compare the root with k, if it's bigger than k, we print the root and recursively call the function on the left binary heap and the right binary heap. Else, we return from the current function call, meaning this below this level, there isn't any value that is bigger than k.
So, the pseudocode will look like,
Last updated
