Priority Queue in C++ STL
In C++, priority queue is a type of queue in which there is some priority assigned to the elements. According to this priority, elements are removed from the queue. By default, the value of the element being inserted is considered as priority. Higher its value, higher its priority. But this can be changed to any desired priority scheme as per requirement.
Example:
#include <iostream>
#include <queue>
using namespace std;
int main() {
// Creating a priority queue of integers
priority_queue<int> pq;
pq.push(9);
pq.push(10);
pq.push(6);
cout << pq.top() << " ";
return 0;
}
Output
10
Explanation: In the above program, we created a priority queue of integers that contains the elements 9, 10 and 6. The top element, which is the largest value in the queue, is then printed.
Syntax
Priority queue is defined as std::priority_queue inside <queue> header file.
priority_queue<T, c, comp> pq;
where,
- T: Type of the priority queue
- pq: Name assigned to the priority queue.
- c: Underlying container. Uses vector as default.
- comp: It is a binary predicate function that tells priority queue how to compare two elements. It is used to set the custom priority parameter and scheme. It is optional and if not provided, maximum value gets maximum priority.
Internal Working
Priority queue container provides the built-in implementation of a binary heap data structure. There can be two types of heaps,
- Max-heap in which the priority is given to the largest element. (Default)
- Min-heap in which the priority is given to the smallest element.
Priority queue is a container adaptor generally built over vector container. We can implement both of these heaps in priority queue.
Declaration and Initialization
Priority queue can be declared and initialized in multiple ways as shown in the below example:
#include <bits/stdc++.h>
using namespace std;
void print(priority_queue<int> pq) {
while (!pq.empty()) {
cout << pq.top() << " ";
pq.pop();
}
}
int main() {
// Create empty priority queue
priority_queue<int> pq1;
// Insert values
pq1.push(9);
pq1.push(8);
pq1.push(6);
print(pq1);
cout << endl;
// Creating priority queue from other container
vector<int> v = {9, 8, 6, 10, 4, 2};
priority_queue<int> pq2(v.begin(), v.end());
print(pq2);
return 0;
}
Output
9 8 6 10 9 8 6 4 2
Explanation: In the above program, two priority queues are initialized in the following ways:
- Statement priority_queue<int> pq1 creates an empty priority queue of integers. Elements are later inserted.
- Statement priority_queue<int> pq2(v.begin(), v.end()) creates a priority queue and initializes it with the same elements as those in the vector v. We can use any other container too.
Both priority queues will have the largest element at the top.
Basic Operations
Here are the basic operations that can be performed on a priority queue:
1. Inserting Elements
Elements can be inserted in the priority queue using push() method. After insertion, priority queue reorganize itself in such a way that the highest priority element is always at the top.
Example:
#include <bits/stdc++.h>
using namespace std;
int main() {
priority_queue<int> pq;
// Inserting elements
pq.push(9);
pq.push(8);
pq.push(6);
cout << pq.top();
return 0;
}
Output
9
Explanation: In the above program, elements 9, 8 and 6 are inserted into the priority queue using push() method one by one. After insertion, the largest element 9 is at the top.
2. Accessing Elements
Only the top element of the priority queue can be accessed using top() method. It is the element with the highest priority in priority queue.
Example:
#include <bits/stdc++.h>
using namespace std;
int main() {
priority_queue<int> pq;
pq.push(9);
pq.push(8);
pq.push(6);
// Accessing top element
cout << pq.top();
return 0;
}
Output
9
3. Deleting Elements
In priority queue, deletion can only be done from the top of the priority queue using pop()method. It means that we can only remove the element with highest priority in one move. After deletion, the priority queue rearranges itself such that the next greatest priority element becomes the top element.
#include <bits/stdc++.h>
using namespace std;
int main() {
priority_queue<int> pq;
pq.push(9);
pq.push(8);
pq.push(6);
// Delete top element
pq.pop();
cout << pq.top();
return 0;
}
Output
8
Explanation: In this example, we deleted the top element using pop() method, which is 9. This shifts the next greatest element 8 to the top.
4. Pseudo Traversal
In priority queue, we can only access top element of the priority queue, so we cannot directly traverse it. However, we can create a copy of the priority queue, access and delete the top element and repeat this process until the copied priority queue is empty. In this way, we can effectively traverse all the elements of the priority queue.
Example:
#include <bits/stdc++.h>
using namespace std;
int main() {
priority_queue<int> pq;
pq.push(9);
pq.push(8);
pq.push(6);
// Create a copy
priority_queue<int> temp(pq);
// Traverse
while(!temp.empty()) {
cout << temp.top() << " ";
temp.pop();
}
return 0;
}
Output
9 8 6
5. Changing Priority Queue Order
All the above operations are demonstrated on a priority queue implementing max heap. This can be changed by using a custom comparator in which you define the priority parameter and how to compare them.
If you only want to assign highest priority to the smallest element (min-heap), then inbuilt greater<type> functional object can be used.
Example:
#include <bits/stdc++.h>
using namespace std;
int main() {
// Creating priority queue
priority_queue<int, vector<int>,
greater<int>> pq;
pq.push(9);
pq.push(8);
pq.push(6);
auto temp = pq;
while(!temp.empty()) {
cout << temp.top() << " ";
temp.pop();
}
return 0;
}
Output
6 8 9
Explanation: In the above program, even though vector is default container, we still have to pass it because the comparator is third template argument. So, we have to pass all the arguments before it.
Time Complexity
The below table lists the time complexity of the above operations on priority queue:
Operation | Time Complexity |
---|---|
Add element | O(log n) |
Delete element | O(log n) |
Find maximum element in max heap. | O(1) |
Find minimum element in min heap. | O(1) |
Initialize priority queue from another container. | O(n) |
Other Common Operations
The following are some more operations on priority queue that will help you become more familiarize with this container:
Priority Queue vs Queue
Following is the primary differences between priority queue and queue in C++:
- A queue follows the First in First Out (FIFO) principle, where the first element inserted is the first element to be removed.
- A priority queue stores elements in order of priority, where the highest priority element is always at the top no matter when it is inserted.
All Member Functions
Following is the list of all member functions of std::priority_queue class in C++:
Function | Definition |
---|---|
empty() | Returns whether the priority queue is empty. |
size() | Returns the size of the priority queue. |
top() | Returns top element of the priority queue |
push() | Adds the element into the priority queue. |
pop() | Deletes the top element of the priority queue. |
swap() | Used to swap the contents of two priority queues provided the queues must be of the same type, although sizes may differ. |
emplace() | Used to insert a new element into the priority queue container. |