Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
What are Heaps? Priority Queue | Real World Usage Like NewsFeed Design
Feb 5, 2025
228 views
Written by Prashant Basnet
π Welcome to my Signature, a space between logic and curiosity.
Iβm a Software Development Engineer who loves turning ideas into systems that work beautifully.
This space captures the process: the bugs, breakthroughs, and βahaβ moments that keep me building.
Binary tree, Binary search tree, full and complete binary tree we can combine these ideas together so that we can learn a new assistant data structure which is HEAP.
From heap, we can learn about priority queue which is a variation on the queue data structure and is much more helpful .
Before understanding what is heap?
Let's first understand why do we need heap?
We use heap every day, using facebook, instagram, linkedin , youtube
every thing organizes data based on a priority. For example, facebook might show you the top post that matched your profile based preferences, or videos that has maximum retention rate.
With array, we have random access, it allowed us to randomly access any element using index. In linked list, we can change things dynamically, but finding a node is linear time of O(N).
Heaps are little bit different, compared to binary search tree, look up takes more time but what's effective?
Why use binary heap?
Binary heaps are really really great at doing comparative operation.
101 72 33 2 45 5 1A complete binary tree are ones where every single level is full expect for the very last level. But if there are nodes in the last level it must be pushed to the left as possible.
Two Variations on Heap:
Max Heap
50 40 25 20. 35. 10. 15Keeping these rules in mind, the main thing to focus on is that the root node of a max heap is the greatest value in this entire heap.
Min Heap:
Up until now, working with binary tree, we get the root node as an object.
Heap: 50 / \ 40 25 / \ / \ 20 35 10 15array = [50 , 40 , 25, 20, 35, 10, 15] 0 1. 2. 3. 4. 5. 6Only difference between array and object of tree node is that using array we need to figure out some mathematical formula that help us define the relationship between nodes.
Think about the relationship related to indices of the values inside our array.
Mathematical Relationships:
50 / \ 40 25 / \ / \ 20 35 10 151. Parent Node:
To get the parent of any node
10 has index of 5, using this formula
2. Left Child:
To get the left child of any node
let's find the left chid of 40, 40 has index 1
3. Right Child
To get the right child of any node
let's find the right child of 40, index = 1
Insertion:
Insert 45
50 / \ 40 25 / \ / \ 20 35 10 15The only way we can insert 45 is at the next available sport. Following BFS order
50 / \ 40 25 / \ / \ 20 35 10 15 / 4520 < 45 , and also 45 is greater than 40.
We need to rearrange our max heap.
Steps to Follow:
1. Take 45 and it's immediate parent i.e 20, then compare, is 45 greater than 20?
50 / \ 40 25 / \ / \ 45 35 10 15 / 202. Again, compare the new parent i.e (45) greather than it's immediate parent i.e (40)?
50 / \ 45 25 / \ / \ 40 35 10 15 / 203. Then compare again, is 45 greater than 50?
Thus our heap is valid and new final heap.
**************** With Array********************
50 / \ 40 25 / \ / \ 20 35 10 15[50, 45, 25, 20, 35, 10, 15] 0 1 2 3 4 5 6In the exact same vein, what we need to do, we just insert 45 at the end of an array.
50 / \ 40 25 / \ / \ 20 35 10 15 / 451. Compare new value i.e 45 with it's immediate parent value and keep comparing and swapping value until find it's final resting point.
2. Then we compare again,
* # [50, 45, 25, 40, 35, 10, 15, 20] 0 1 2 3 4 5 6 73. Compare one more time,
Thus the final resting point
Now, what about removing the nodes from Heap?
The reason why we implement the heap, particularly max heap is: we supply values, & whenever we want to retrieve a value , it has to give the greatest value amongst the value we supplied.
So this is why max heap, whenever we talk about removal, deletion or retrieving a value form this heap, the only condition we want to satisfy is that we are getting the greatest value, which is root value in max heap.
75 / \ 50 25 / \ / \ 45 35 10 15 / \ 20 40let call remove here, which will remove the 75 and return it
() / \ 50 25 / \ / \ 45 35 10 15 / \ 20 40Now we need to restructure our heap so we can maintain not only the rule that the max heap has greatest value at the top of the tree, but also it is still a complete binary tree.
Procedure to remove:
1. We are going to take the right most value at the last level as placeholder root
40 / \ 50 25 / \ / \ 45 35 10 15 / 202. Starting from the root value, it's two children. Which one is greater value?
50 / \ 40 25 / \ / \ 45 35 10 15 / 203. Do the same iteration with 40 again, amongst it's children which one is greater?
50 / \ 45 25 / \ / \ 40 35 10 15 / 204. Once again, we going to say does 49 has two children?
So now we know 40 is at it's final resting point.
Now we see that 50 is the greatest value inside the max heap once again.
**************** With Array********************
75 / \ 50 25 / \ / \ 45 35 10 15 / \ 20 401. Remove 75, and push 40 in it's place
[40, 50, 25, 45, 35, 10, 15, 20]. 0 1 2 3 4 5 6 740 / \ 50 25 / \ / \ 45 35 10 15 / 202. Now let's compare and find the correct place of our new value.
[50, 40, 25, 45, 35, 10, 15, 20]. 0 1 2 3 4 5 6 750 / \ 40 25 / \ / \ 45 35 10 15 / 203. Once again , we take 40 @ index 1 and find it's two children
[50, 45, 25, 40, 35, 10, 15, 20]. 0 1 2 3 4 5 6 750 / \ 45 25 / \ / \ 40 35 10 15 / 204. Once again we take 40 @ position 3, we get it's child
/* functions to implement on pq: 1. insert 2. remove 3. peek 4. size 5. isEmpty 1. _leftChild 2. rightChild 3. _parent 4. _swap 5. _bubbleUp 6. _bubbleDown */class PQ{ constructor(comparator){ this.compare = comparator this.heap = [] } _leftChild(index){ return (index * 2) + 1 } _rightChild(index){ return (index * 2) + 2 } _parent(index){ return (index - 1) / 2 } _swap(i, j){ let temp = this.heap[i] this.heap[i] = this.heap[j] this.heap[j] = temp } _compare(i, j){ return this.heap[i] > this.heap[j] }//for insertion _bubbleUp(){ let addedItemIdx = this.size() - 1 while(this._compare(this._parent(addedItemIdx), addedItemIdx)){ this._swap( addedItemIdx, this._parent(addedItemIdx)) addedItemIdx = this._parent(addedItemIdx) } }// for deletion _bubbleDown(){ let nodeIdx = 0 while( 0 < this._leftChild(nodeIdx) && this._compare(this._leftChild(nodeIdx), nodeIdx) || 0 < this._rightChild(nodeIdx) && this._compare(this._rightChild(nodeIdx), nodeIdx)){let greaterIdx = this.rightChildIdx(nodeIdx) && this._compare( this._rightChild(nodeIdx), this._leftChild(nodeIdx)) ? this._rightChild(nodeIdx) : this._leftChild(nodeIdx) this._swap(greaterIdx, nodeIdx) nodeIdx = greaterIdx } }isEmpty(){ return this.heap.length === 0 } size(){ return this.heap.length } insert(value){ // if(this.isEmpty()){} this.heap.push(value) this._bubbleUp() return true }removal(){ // need to remove the top elememnt // for that pop will not work // swap 1st and last elem // and pop out the last one and return it if(this.size() > 1){ this._swap(0, this.size - 1 ) } const poppedVal = this.heap.pop() this._bubbleDown() return poppedVal } peek(){ return this.heap[0] } }#dataStructures #algorithm #systemDesign #NewsFeed #javascript