Priority Queue is an extension of the queue with the following properties:
- Every item has a priority associated with it.
- An element with high priority is dequeued before an element with low priority.
- If two elements have the same priority, they are served according to their order in the queue.
A Binary Heap is a Binary Tree with the following properties:
- It is a Complete Tree. This property of Binary Heap makes them suitable to be stored in an array.
- A Binary Heap is either Min Heap or Max Heap.
- In a Min Binary Heap, the key at the root must be minimum among all keys present in Binary Heap. The same property must be recursively true for all nodes in Binary Tree.
- Similarly, in a Max Binary Heap, the key at the root must be maximum among all keys present in Binary Heap. The same property must be recursively true for all nodes in Binary Tree.
Operation on Binary Heap
- insert(p): Inserts a new element with priority p.
- extractMax(): Extracts an element with maximum priority.
- remove(i): Removes an element pointed by an iterator i.
- getMax(): Returns an element with maximum priority.
- changePriority(i, p): Changes the priority of an element pointed by i to p.
Example of A Binary Max Heap
- Suppose below is the given Binary Heap that follows all the properties of Binary Max Heap.
- Now a node with value 32 need to be insert in the above heap: To insert an element, attach the new element to any leaf. For Example A node with priority 32 can be added to the leaf of the node 7. But this violates the heap property. To maintain the heap property, shift up the new node 32.
- Shift Up Operation get node with 32 at the correct position: Swap the incorrectly placed node with its parent until the heap property is satisfied. For Example: As node 7 is less than node 32 so, swap node 7 and node 32. Then, swap node 31 and node 32.
- ExtractMax: The maximum value is stored at the root of the tree. But the root of the tree cannot be directly removed. First, it is replaced with any one of the leaves and then removed. For Example: To remove Node 45, it is first replaced with node 7. But this violates the heap property, so move the replaced node down. For that, use shift-down operation.
- ShiftDown operation: Swap the incorrectly placed node with a larger child until the heap property is satisfied. For Example Node 7 is swapped with node 32 then, last it is swapped with node 31.
- ChangePriority: Let the changed element shift up or down depending on whether its priority decreased or increased. For Example: Change the priority of nodes 11 to 35, due to this change the node has to shift up the node in order to maintain the heap property.
- Remove: To remove an element, change its priority to a value larger than the current maximum, then shift it up, and then extract it using extract max. Find the current maximum using getMax.
- GetMax: The max value is stored at the root of the tree. To getmax, just return the value at the root of the tree.
Array Representation of Binary Heap
Since the heap is maintained in form of a complete binary tree, because of this fact the heap can be represented in the form of an array. To keep the tree complete and shallow, while inserting a new element insert it in the leftmost vacant position in the last level i.e., at the end of our array. Similarly, while extracting maximum replace the root with the last leaf at the last level i.e., the last element of the array. Below is the illustration of the same:
Below is the program to implement Priority Queue using Binary Heap:
C++
#include <bits/stdc++.h>
using namespace std;
int H[50];
int size = -1;
int parent( int i)
{
return (i - 1) / 2;
}
int leftChild( int i)
{
return ((2 * i) + 1);
}
int rightChild( int i)
{
return ((2 * i) + 2);
}
void shiftUp( int i)
{
while (i > 0 && H[parent(i)] < H[i]) {
swap(H[parent(i)], H[i]);
i = parent(i);
}
}
void shiftDown( int i)
{
int maxIndex = i;
int l = leftChild(i);
if (l <= size && H[l] > H[maxIndex]) {
maxIndex = l;
}
int r = rightChild(i);
if (r <= size && H[r] > H[maxIndex]) {
maxIndex = r;
}
if (i != maxIndex) {
swap(H[i], H[maxIndex]);
shiftDown(maxIndex);
}
}
void insert( int p)
{
size = size + 1;
H[size] = p;
shiftUp(size);
}
int extractMax()
{
int result = H[0];
H[0] = H[size];
size = size - 1;
shiftDown(0);
return result;
}
void changePriority( int i, int p)
{
int oldp = H[i];
H[i] = p;
if (p > oldp) {
shiftUp(i);
}
else {
shiftDown(i);
}
}
int getMax()
{
return H[0];
}
void remove ( int i)
{
H[i] = getMax() + 1;
shiftUp(i);
extractMax();
}
int main()
{
insert(45);
insert(20);
insert(14);
insert(12);
insert(31);
insert(7);
insert(11);
insert(13);
insert(7);
int i = 0;
cout << "Priority Queue : " ;
while (i <= size) {
cout << H[i] << " " ;
i++;
}
cout << "\n" ;
cout << "Node with maximum priority : "
<< extractMax() << "\n" ;
cout << "Priority queue after "
<< "extracting maximum : " ;
int j = 0;
while (j <= size) {
cout << H[j] << " " ;
j++;
}
cout << "\n" ;
changePriority(2, 49);
cout << "Priority queue after "
<< "priority change : " ;
int k = 0;
while (k <= size) {
cout << H[k] << " " ;
k++;
}
cout << "\n" ;
remove (3);
cout << "Priority queue after "
<< "removing the element : " ;
int l = 0;
while (l <= size) {
cout << H[l] << " " ;
l++;
}
return 0;
}
|
Java
import java.util.*;
class GFG{
static int []H = new int [ 50 ];
static int size = - 1 ;
static int parent( int i)
{
return (i - 1 ) / 2 ;
}
static int leftChild( int i)
{
return (( 2 * i) + 1 );
}
static int rightChild( int i)
{
return (( 2 * i) + 2 );
}
static void shiftUp( int i)
{
while (i > 0 &&
H[parent(i)] < H[i])
{
swap(parent(i), i);
i = parent(i);
}
}
static void shiftDown( int i)
{
int maxIndex = i;
int l = leftChild(i);
if (l <= size &&
H[l] > H[maxIndex])
{
maxIndex = l;
}
int r = rightChild(i);
if (r <= size &&
H[r] > H[maxIndex])
{
maxIndex = r;
}
if (i != maxIndex)
{
swap(i, maxIndex);
shiftDown(maxIndex);
}
}
static void insert( int p)
{
size = size + 1 ;
H[size] = p;
shiftUp(size);
}
static int extractMax()
{
int result = H[ 0 ];
H[ 0 ] = H[size];
size = size - 1 ;
shiftDown( 0 );
return result;
}
static void changePriority( int i,
int p)
{
int oldp = H[i];
H[i] = p;
if (p > oldp)
{
shiftUp(i);
}
else
{
shiftDown(i);
}
}
static int getMax()
{
return H[ 0 ];
}
static void remove( int i)
{
H[i] = getMax() + 1 ;
shiftUp(i);
extractMax();
}
static void swap( int i, int j)
{
int temp= H[i];
H[i] = H[j];
H[j] = temp;
}
public static void main(String[] args)
{
insert( 45 );
insert( 20 );
insert( 14 );
insert( 12 );
insert( 31 );
insert( 7 );
insert( 11 );
insert( 13 );
insert( 7 );
int i = 0 ;
System.out.print( "Priority Queue : " );
while (i <= size)
{
System.out.print(H[i] + " " );
i++;
}
System.out.print( "\n" );
System.out.print( "Node with maximum priority : " +
extractMax() + "\n" );
System.out.print( "Priority queue after " +
"extracting maximum : " );
int j = 0 ;
while (j <= size)
{
System.out.print(H[j] + " " );
j++;
}
System.out.print( "\n" );
changePriority( 2 , 49 );
System.out.print( "Priority queue after " +
"priority change : " );
int k = 0 ;
while (k <= size)
{
System.out.print(H[k] + " " );
k++;
}
System.out.print( "\n" );
remove( 3 );
System.out.print( "Priority queue after " +
"removing the element : " );
int l = 0 ;
while (l <= size)
{
System.out.print(H[l] + " " );
l++;
}
}
}
|
Python3
H = [ 0 ] * 50
size = - 1
def parent(i) :
return (i - 1 ) / / 2
def leftChild(i) :
return (( 2 * i) + 1 )
def rightChild(i) :
return (( 2 * i) + 2 )
def shiftUp(i) :
while (i > 0 and H[parent(i)] < H[i]) :
swap(parent(i), i)
i = parent(i)
def shiftDown(i) :
maxIndex = i
l = leftChild(i)
if (l < = size and H[l] > H[maxIndex]) :
maxIndex = l
r = rightChild(i)
if (r < = size and H[r] > H[maxIndex]) :
maxIndex = r
if (i ! = maxIndex) :
swap(i, maxIndex)
shiftDown(maxIndex)
def insert(p) :
global size
size = size + 1
H[size] = p
shiftUp(size)
def extractMax() :
global size
result = H[ 0 ]
H[ 0 ] = H[size]
size = size - 1
shiftDown( 0 )
return result
def changePriority(i,p) :
oldp = H[i]
H[i] = p
if (p > oldp) :
shiftUp(i)
else :
shiftDown(i)
def getMax() :
return H[ 0 ]
def Remove(i) :
H[i] = getMax() + 1
shiftUp(i)
extractMax()
def swap(i, j) :
temp = H[i]
H[i] = H[j]
H[j] = temp
insert( 45 )
insert( 20 )
insert( 14 )
insert( 12 )
insert( 31 )
insert( 7 )
insert( 11 )
insert( 13 )
insert( 7 )
i = 0
print ( "Priority Queue : " , end = "")
while (i < = size) :
print (H[i], end = " " )
i + = 1
print ()
print ( "Node with maximum priority :" , extractMax())
print ( "Priority queue after extracting maximum : " , end = "")
j = 0
while (j < = size) :
print (H[j], end = " " )
j + = 1
print ()
changePriority( 2 , 49 )
print ( "Priority queue after priority change : " , end = "")
k = 0
while (k < = size) :
print (H[k], end = " " )
k + = 1
print ()
Remove( 3 )
print ( "Priority queue after removing the element : " , end = "")
l = 0
while (l < = size) :
print (H[l], end = " " )
l + = 1
|
C#
using System;
class GFG{
static int []H = new int [50];
static int size = -1;
static int parent( int i)
{
return (i - 1) / 2;
}
static int leftChild( int i)
{
return ((2 * i) + 1);
}
static int rightChild( int i)
{
return ((2 * i) + 2);
}
static void shiftUp( int i)
{
while (i > 0 &&
H[parent(i)] < H[i])
{
swap(parent(i), i);
i = parent(i);
}
}
static void shiftDown( int i)
{
int maxIndex = i;
int l = leftChild(i);
if (l <= size &&
H[l] > H[maxIndex])
{
maxIndex = l;
}
int r = rightChild(i);
if (r <= size &&
H[r] > H[maxIndex])
{
maxIndex = r;
}
if (i != maxIndex)
{
swap(i, maxIndex);
shiftDown(maxIndex);
}
}
static void insert( int p)
{
size = size + 1;
H[size] = p;
shiftUp(size);
}
static int extractMax()
{
int result = H[0];
H[0] = H[size];
size = size - 1;
shiftDown(0);
return result;
}
static void changePriority( int i,
int p)
{
int oldp = H[i];
H[i] = p;
if (p > oldp)
{
shiftUp(i);
}
else
{
shiftDown(i);
}
}
static int getMax()
{
return H[0];
}
static void Remove( int i)
{
H[i] = getMax() + 1;
shiftUp(i);
extractMax();
}
static void swap( int i, int j)
{
int temp = H[i];
H[i] = H[j];
H[j] = temp;
}
public static void Main(String[] args)
{
insert(45);
insert(20);
insert(14);
insert(12);
insert(31);
insert(7);
insert(11);
insert(13);
insert(7);
int i = 0;
Console.Write( "Priority Queue : " );
while (i <= size)
{
Console.Write(H[i] + " " );
i++;
}
Console.Write( "\n" );
Console.Write( "Node with maximum priority : " +
extractMax() + "\n" );
Console.Write( "Priority queue after " +
"extracting maximum : " );
int j = 0;
while (j <= size)
{
Console.Write(H[j] + " " );
j++;
}
Console.Write( "\n" );
changePriority(2, 49);
Console.Write( "Priority queue after " +
"priority change : " );
int k = 0;
while (k <= size)
{
Console.Write(H[k] + " " );
k++;
}
Console.Write( "\n" );
Remove(3);
Console.Write( "Priority queue after " +
"removing the element : " );
int l = 0;
while (l <= size)
{
Console.Write(H[l] + " " );
l++;
}
}
}
|
Javascript
<script>
var H = Array(50).fill(0);
var size = -1;
function parent(i)
{
return parseInt((i - 1) / 2);
}
function leftChild(i)
{
return parseInt((2 * i) + 1);
}
function rightChild(i)
{
return parseInt((2 * i) + 2);
}
function shiftUp( i)
{
while (i > 0 && H[parent(i)] < H[i]) {
swap(parent(i), i);
i = parent(i);
}
}
function swap(i, j)
{
var temp = H[i];
H[i] = H[j];
H[j] = temp;
}
function shiftDown( i)
{
var maxIndex = i;
var l = leftChild(i);
if (l <= size && H[l] > H[maxIndex]) {
maxIndex = l;
}
var r = rightChild(i);
if (r <= size && H[r] > H[maxIndex]) {
maxIndex = r;
}
if (i != maxIndex) {
swap(i, maxIndex);
shiftDown(maxIndex);
}
}
function insert( p)
{
size = size + 1;
H[size] = p;
shiftUp(size);
}
function extractMax()
{
var result = H[0];
H[0] = H[size];
size = size - 1;
shiftDown(0);
return result;
}
function changePriority(i, p)
{
var oldp = H[i];
H[i] = p;
if (p > oldp) {
shiftUp(i);
}
else {
shiftDown(i);
}
}
function getMax()
{
return H[0];
}
function remove(i)
{
H[i] = getMax() + 1;
shiftUp(i);
extractMax();
}
insert(45);
insert(20);
insert(14);
insert(12);
insert(31);
insert(7);
insert(11);
insert(13);
insert(7);
var i = 0;
document.write( "Priority Queue : " );
while (i <= size) {
document.write( H[i] + " " );
i++;
}
document.write( "<br>" );
document.write( "Node with maximum priority : "
+ extractMax() + "<br>" );
document.write( "Priority queue after "
+ "extracting maximum : " );
var j = 0;
while (j <= size) {
document.write( H[j] + " " );
j++;
}
document.write( "<br>" );
changePriority(2, 49);
document.write( "Priority queue after "
+ "priority change : " );
var k = 0;
while (k <= size) {
document.write( H[k] + " " );
k++;
}
document.write( "<br>" );
remove(3);
document.write( "Priority queue after "
+ "removing the element : " );
var l = 0;
while (l <= size) {
document.write( H[l] + " " );
l++;
}
</script>
|
Output
Priority Queue : 45 31 14 13 20 7 11 12 7
Node with maximum priority : 45
Priority queue after extracting maximum : 31 20 14 13 7 7 11 12
Priority queue after priority change : 49 20 31 13 7 7 11 12
Priority queue after removing the element : 49 20 31 12 7 7 11
Time Complexity: The time complexity of all the operation is O(log N) except for GetMax() which has time complexity of O(1).
Auxiliary Space: O(N)
Method – 2
below is also a valid method to implement this priority queue using a max heap. this code is a generic method to implement a priority queue using a class-based structure. here in the implementation part, we are using a generic template (not a specific data type) so this implementation works for all data types.
C++
#include <iostream>
#include <vector>
using namespace std;
template < typename T>
class PriorityQueue {
private :
vector<T> data;
public :
PriorityQueue() {}
void Enqueue(T item) {
data.push_back(item);
int ci = data.size() - 1;
while (ci > 0) {
int pi = (ci - 1) / 2;
if (data[ci] <= data[pi])
break ;
T tmp = data[ci];
data[ci] = data[pi];
data[pi] = tmp;
ci = pi;
}
}
T Dequeue() {
int li = data.size() - 1;
T frontItem = data[0];
data[0] = data[li];
data.pop_back();
--li;
int pi = 0;
while ( true ) {
int ci = pi * 2 + 1;
if (ci > li)
break ;
int rc = ci + 1;
if (rc <= li && data[rc] < data[ci])
ci = rc;
if (data[pi] >= data[ci])
break ;
T tmp = data[pi];
data[pi] = data[ci];
data[ci] = tmp;
pi = ci;
}
return frontItem;
}
T Peek() {
T frontItem = data[0];
return frontItem;
}
int Count() {
return data.size();
}
};
int main()
{
PriorityQueue< int > pq;
pq.Enqueue(1);
cout << "Size of pq is : " << pq.Count() <<
" and Peek Element is : " << pq.Peek() << endl;
pq.Enqueue(10);
pq.Enqueue(-8);
cout << "Size of pq is : " << pq.Count() <<
" and Peek Element is : " << pq.Peek() << endl;
pq.Dequeue();
cout << "Size of pq is : " << pq.Count() <<
" and Peek Element is : " << pq.Peek() << endl;
pq.Dequeue();
cout << "Size of pq is : " << pq.Count() <<
" and Peek Element is : " << pq.Peek() << endl;
pq.Enqueue(25);
cout << "Size of pq is : " << pq.Count() <<
" and Peek Element is : " << pq.Peek() << endl;
return 0;
}
|
Java
import java.util.ArrayList;
import java.util.List;
public class GFG {
static class PriorityQueue<T extends Comparable<T>> {
private List<T> data;
public PriorityQueue() {
this .data = new ArrayList<T>();
}
public void Enqueue(T item) {
data.add(item);
int ci = data.size() - 1 ;
while (ci > 0 ) {
int pi = (ci - 1 ) / 2 ;
if (data.get(ci).compareTo(data.get(pi)) <= 0 )
break ;
T tmp = data.get(ci);
data.set(ci, data.get(pi));
data.set(pi, tmp);
ci = pi;
}
}
public T Dequeue() {
int li = data.size() - 1 ;
T frontItem = data.get( 0 );
data.set( 0 , data.get(li));
data.remove(li);
--li;
int pi = 0 ;
while ( true ) {
int ci = pi * 2 + 1 ;
if (ci > li)
break ;
int rc = ci + 1 ;
if (rc <= li && data.get(rc).compareTo(data.get(ci)) < 0 )
ci = rc;
if (data.get(pi).compareTo(data.get(ci)) >= 0 )
break ;
T tmp = data.get(pi);
data.set(pi, data.get(ci));
data.set(ci, tmp);
pi = ci;
}
return frontItem;
}
public T Peek() {
T frontItem = data.get( 0 );
return frontItem;
}
public int Count() {
return data.size();
}
}
public static void main(String[] args) {
PriorityQueue<Integer> pq = new PriorityQueue<Integer>();
pq.Enqueue( 1 );
System.out.println( "Size of pq is : " + pq.Count() + " and Peek Element is : " + pq.Peek());
pq.Enqueue( 10 );
pq.Enqueue(- 8 );
System.out.println( "Size of pq is : " + pq.Count() + " and Peek Element is : " + pq.Peek());
pq.Dequeue();
System.out.println( "Size of pq is : " + pq.Count() + " and Peek Element is : " + pq.Peek());
pq.Dequeue();
System.out.println( "Size of pq is : " + pq.Count() + " and Peek Element is : " + pq.Peek());
pq.Enqueue( 25 );
System.out.println( "Size of pq is : " + pq.Count() + " and Peek Element is : " + pq.Peek());
}
}
|
Python3
import heapq
class PriorityQueue:
def __init__( self ):
self ._queue = []
self ._index = 0
def enqueue( self , item, priority):
heapq.heappush( self ._queue, (priority, self ._index, item))
self ._index + = 1
def dequeue( self ):
return heapq.heappop( self ._queue)[ - 1 ]
def peek( self ):
return self ._queue[ 0 ][ - 1 ]
def count( self ):
return len ( self ._queue)
if __name__ = = "__main__" :
pq = PriorityQueue()
pq.enqueue( 1 , 1 )
print ( "Size of pq is : " , pq.count(), " and Peek Element is : " , pq.peek())
pq.enqueue( 10 , 2 )
pq.enqueue( - 8 , 3 )
print ( "Size of pq is : " , pq.count(), " and Peek Element is : " , pq.peek())
pq.dequeue()
print ( "Size of pq is : " , pq.count(), " and Peek Element is : " , pq.peek())
pq.dequeue()
print ( "Size of pq is : " , pq.count(), " and Peek Element is : " , pq.peek())
pq.enqueue( 25 , 4 )
print ( "Size of pq is : " , pq.count(), " and Peek Element is : " , pq.peek())
|
C#
using System;
using System.Collections.Generic;
class GFG {
class PriorityQueue<T> where T : IComparable<T> {
private List<T> data;
public PriorityQueue() {
this .data = new List<T>();
}
public void Enqueue(T item) {
data.Add(item);
int ci = data.Count - 1;
while (ci > 0) {
int pi = (ci - 1) / 2;
if (data[ci].CompareTo(data[pi]) <= 0)
break ;
T tmp = data[ci]; data[ci] = data[pi]; data[pi] = tmp;
ci = pi;
}
}
public T Dequeue() {
int li = data.Count - 1;
T frontItem = data[0];
data[0] = data[li];
data.RemoveAt(li);
--li;
int pi = 0;
while ( true ) {
int ci = pi * 2 + 1;
if (ci > li) break ;
int rc = ci + 1;
if (rc <= li && data[rc].CompareTo(data[ci]) < 0)
ci = rc;
if (data[pi].CompareTo(data[ci]) >= 0) break ;
T tmp = data[pi]; data[pi] = data[ci]; data[ci] = tmp;
pi = ci;
}
return frontItem;
}
public T Peek() {
T frontItem = data[0];
return frontItem;
}
public int Count() {
return data.Count;
}
}
public static void Main( string [] args) {
var pq = new PriorityQueue< int >();
pq.Enqueue(1);
Console.WriteLine( "Size of pq is : " + pq.Count() + " and Peek Element is : " + pq.Peek());
pq.Enqueue(10);
pq.Enqueue(-8);
Console.WriteLine( "Size of pq is : " + pq.Count() + " and Peek Element is : " + pq.Peek());
pq.Dequeue();
Console.WriteLine( "Size of pq is : " + pq.Count() + " and Peek Element is : " + pq.Peek());
pq.Dequeue();
Console.WriteLine( "Size of pq is : " + pq.Count() + " and Peek Element is : " + pq.Peek());
pq.Enqueue(25);
Console.WriteLine( "Size of pq is : " + pq.Count() + " and Peek Element is : " + pq.Peek());
}
}
|
Javascript
class PriorityQueue {
constructor() {
this .data = [];
}
enqueue(item) {
this .data.push(item);
let ci = this .data.length - 1;
while (ci > 0) {
let pi = Math.floor((ci - 1) / 2);
if ( this .data[ci] <= this .data[pi])
break ;
let tmp = this .data[ci];
this .data[ci] = this .data[pi];
this .data[pi] = tmp;
ci = pi;
}
}
dequeue() {
let li = this .data.length - 1;
let frontItem = this .data[0];
this .data[0] = this .data[li];
this .data.pop();
--li;
let pi = 0;
while ( true ) {
let ci = pi * 2 + 1;
if (ci > li)
break ;
let rc = ci + 1;
if (rc <= li && this .data[rc] < this .data[ci])
ci = rc;
if ( this .data[pi] >= this .data[ci])
break ;
let tmp = this .data[pi];
this .data[pi] = this .data[ci];
this .data[ci] = tmp;
pi = ci;
}
return frontItem;
}
peek() {
let frontItem = this .data[0];
return frontItem;
}
count() {
return this .data.length;
}
}
let pq = new PriorityQueue();
pq.enqueue(1);
console.log(`Size of pq is: ${pq.count()} and Peek Element is: ${pq.peek()}`);
pq.enqueue(10);
pq.enqueue(-8);
console.log(`Size of pq is: ${pq.count()} and Peek Element is: ${pq.peek()}`);
pq.dequeue();
console.log(`Size of pq is: ${pq.count()} and Peek Element is: ${pq.peek()}`);
pq.dequeue();
console.log(`Size of pq is: ${pq.count()} and Peek Element is: ${pq.peek()}`);
pq.enqueue(25);
console.log(`Size of pq is: ${pq.count()} and Peek Element is: ${pq.peek()}`);
|
Output
Size of pq is : 1 and Peek Element is : 1
Size of pq is : 3 and Peek Element is : 10
Size of pq is : 2 and Peek Element is : 1
Size of pq is : 1 and Peek Element is : -8
Size of pq is : 2 and Peek Element is : 25
Time Complexity: O(log(n)) for EnQueue operation and O(log(n)) for Dequeue operation
Space complexity: O(n) (as we need n size array for implementation)
Feeling lost in the world of random DSA topics, wasting time without progress? It’s time for a change! Join our DSA course, where we’ll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!