Priority Queue In C++ - C++ Programming Tutorial
C++ Course / Data Structures / Priority Queue In C++

Priority Queue In C++

BLUF: Mastering Priority Queue In C++ is a critical step in becoming a proficient C++ developer. This lesson provides a deep dive into the syntax, performance considerations, and real-world applications of this concept.
Key Performance Insight: Priority Queue In C++

C++ is renowned for its efficiency. Learn how Priority Queue In C++ enables low-level control and high-performance computing in the tutorial below.

In C++, the priority queue represents a specialized container in the STL that focuses solely on the element with the highest priority. While a regular queue adheres to a FIFO (First In First Out) policy, a priority queue removes elements based on their priority, with the highest priority element being dequeued first.

It is similar to the ordinary queue in certain aspects but differs in the following ways:

  • Each element in a priority queue has an associated priority, unlike a regular queue where all elements are treated equally.
  • The element with the highest priority in a priority queue will be removed first, while the queue follows the FIFO(First-In-First-Out) policy means the element that is inserted first will be deleted first.
  • If more than one element exists with the same priority, then the order of the elements in a queue will be taken into consideration.
  • Syntax

It has the following syntax:

Example

Priority_queue<int>variable_name;

In this particular syntax,

  • int denotes the data type of the element.
  • variable_name represents the identifier of the variable.

Priority queue container provides a pre-built implementation of the binary heap data structure. There are typically two variations of heaps that can be utilized.

1) Max Heap Priority Queue (by default)

In a Max Heap priority queue, the item with the greatest value is given the highest priority and is retrieved first. This is the default functionality of std::priority_queue in the C++ programming language.

Syntax

It has the following syntax:

Example

std::priority_queue<data_type> maxHeap;

In this particular notation,

  • data_type signifies the type of elements that are stored within the priority queue.
  • Max Heap Priority Queue Example

Let's consider a straightforward example to demonstrate the implementation of a max heap priority queue in C++.

Example

Example

#include <iostream>

#include <queue>

int main() {

    std::priority_queue<int> maxHeap;

    maxHeap.push(10);

    maxHeap.push(30);

    maxHeap.push(20);

    maxHeap.push(5);

    std::cout << "Elements in max-heap order: ";

    while (!maxHeap.empty()) {

        std::cout << maxHeap.top() << " ";

        maxHeap.pop();

    }

    return 0;

}

Output:

Output

Elements in max-heap order: 30 20 10 5

Explanation

In this instance, the priority_queue<int> is implemented with std::less<int> as its default comparator. The element with the highest value (30) is assigned the topmost priority, leading to elements being displayed in a descending order based on their values.

2) Min Heap Priority Queue (Custom Comparator)

In a priority queue implemented as a Min Heap, the element with the smallest value is considered to have the highest priority and is retrieved first. This behavior can be accomplished by employing a user-defined comparator such as std::greater.

Syntax

It has the following syntax:

Example

std::priority_queue<int, std::vector<int>, std::greater<int>> minHeap;

In this syntax,

  • Vector<int>: It represents the STL Container.
  • greater<int>: It represents the comparator class.
  • Min Heap Priority Queue Example

Let's consider a scenario to demonstrate the minimum heap within the priority queue in C++.

Example

Example

#include <iostream>

#include <queue>

#include <vector>

#include <functional>

int main() {

    std::priority_queue<int, std::vector<int>, std::greater<int>> minHeap;

    minHeap.push(10);

    minHeap.push(30);

    minHeap.push(20);

    minHeap.push(5);

    std::cout << "Elements in min-heap order: ";

    while (!minHeap.empty()) {

        std::cout << minHeap.top() << " ";

        minHeap.pop();

    }

    return 0;

}

Output:

Output

Elements in min-heap order: 5 10 20 30

Explanation

The third parameter in the template, std::greater<int>, alters the functionality to form a min-heap. The element with the smallest value (5) is given the topmost priority. The elements are displayed in ascending order based on their values.

Let's explore the concept of priority queues using a basic illustration.

In the preceding diagram, elements were added using the push method, and the process of inserting is the same as a standard queue. However, during deletion with the pop method, the element with the topmost priority will be removed initially.

Basic Operations of Priority Queues

Various fundamental functions of priority queues in C++ include:

1) Inserting Elements

In priority queues, the add function is employed to add elements to the queue. The heap condition remains unchanged with each addition as it automatically places the highest priority item (usually the greatest) at the top.

2) Accessing Top Element

The top method retrieves the highest element in the priority queue, which is determined by its default highest priority value. This data structure enables quick access to the maximum element with a time complexity of O(1) without removing it. By using the top function, we can observe the maximum value before proceeding with operations like pop.

Inserting and Accessing Top Element Example

Let's consider a scenario to demonstrate the process of inserting and retrieving elements in a priority queue.

Example

Example

#include <iostream>

#include <queue>

using namespace std;

int main() {

    priority_queue<int> pq;

    pq.push(70);

    pq.push(60);

    pq.push(90);

    pq.push(55);

    cout << "Maximum element: " << pq.top() << endl;

    return 0;

}

Output:

Output

Maximum element: 90

Explanation

In this instance, the priority queue is populated with the elements 70, 60, 90, and 55 sequentially. When organized as a max-heap, the element 90 naturally becomes the highest priority. Utilizing pq.top accurately yields the value 90, showcasing the queue's adherence to prioritizing elements during its functions.

3) Deleting Top Element

The pop method is employed to remove the element positioned at the front (top element) of a priority queue according to its priority level. It is recommended for users to utilize the top method initially to fetch the eliminated element since pop does not provide any return value. Subsequently, the queue system proceeds to process the subsequent largest element, which seamlessly transitions into the topmost position.

Deletion of Top Element in Priority Queue Example

Let's consider an illustration to demonstrate the process of removing the highest-priority item from the priority queue.

Example

Example

#include <iostream>

#include <queue>

using namespace std;

int main() {

    priority_queue<int> pq;

    pq.push(15);

    pq.push(35);

    pq.push(25);

    cout << "Before pop, top: " << pq.top() << endl;

    pq.pop();

    cout << "After pop, new top: " << pq.top() << endl;

    return 0;

}

Output:

Output

Before pop, top: 35

After pop, new top: 25

Explanation

The priorityqueue is populated with the values 15, 35, and 25. Among these elements, 35 holds the highest priority in the priorityqueue because of its size compared to others prior to executing the pop function. Once pop is executed, 35 is taken out of the queue, resulting in 25 taking over as the element with the highest priority.

4) Traversing (Pseudo Traversal)

A priority queue doesn't offer direct traversal like vectors or lists. To access all elements, you start with top and then perform a pop immediately. The elements are printed out in descending order due to the priority queue's default max-heap structure.

C++ Traversing Example in Priority Queue

Let's consider an illustration to demonstrate navigating through the priority queue in C++.

Example

Example

#include <iostream>

#include <queue>

using namespace std;

int main() {

    priority_queue<int> pq;

    pq.push(20);

    pq.push(10);

    pq.push(30);

    cout << "Elements in descending order: ";

    while (!pq.empty()) {

        cout << pq.top() << " ";

        pq.pop();

    }

    cout << endl;

    return 0;

}

Output:

Output

Elements in descending order: 30 20 10

Explanation

In this instance, the numbers 20, 10, and 30 are added. Subsequently, the highest position in the priority queue contains the largest value due to its specific queue structure. The process then proceeds with 20 as the next largest value, followed by the printing of 10. The order of printing maintains a descending pattern for all the inserted elements.

5) Changing Priority Queue Order

C++ programmers have the ability to modify the order of a priority queue within their software by defining a custom comparator. The standard behavior of a C++ priority queue is to operate as a max-heap, where elements with higher priority are placed at the top of the structure. By using a custom comparator, developers can change the default max-heap configuration to a min-heap or implement a personalized prioritization system.

Example of Changing the Priority Queue Order

Let's consider an example to demonstrate how to modify the order of elements in a priority queue using C++.

Example

Example

#include <iostream>

#include <queue>

#include <vector>

using namespace std;

int main() {

    // Custom comparator for a min-heap (using greater<int>)

    priority_queue<int, vector<int>, greater<int>> minHeap;

    minHeap.push(40);

    minHeap.push(10);

    minHeap.push(30);

    cout << "Top element (min-heap): " << minHeap.top() << endl; // Output: 10

    return 0;

}

Output:

Output

Top element (min-heap): 10

Explanation

The application of the greater<int> method converts standard max-heaps into min-heaps within the software. The highest position in a min-heap holds the smallest element among all. When the queue is processed, the result reflects 10 as it signifies the minimum element saved in the priority queue.

Time Complexity

Operation Time Complexity Explanation
pop() O(log n) Removing the top element requires reheapifying the structure.
push() O(log n) Inserting an element requires maintaining the heap property (logarithmic).
top() O(1) Accessing the maximum (or minimum) element is done in constant time.
empty() / size() O(1) Checking if the queue is empty or getting its size is constant time.
Traversal via popping O(n log n) Popping all n elements takes log n time each, totalling to n log n.

Member Function of Priority Queue

Various member methods of priority queues in C++ include:

Function Description
push() It inserts a new element in a priority queue.
pop() It removes the top element from the queue, which has the highest priority.
top() This function is used to address the topmost element of a priority queue.
size() It determines the size of a priority queue.
empty() It verifies whether the queue is empty or not. Based on the verification, it returns the status.
swap() It swaps the elements of a priority queue with another queue having the same type and size.
emplace() It inserts a new element at the top of the priority queue.

C++ Priority Queue Example

Let's explore a different instance of a priority queue in C++.

Example

Example

#include <iostream>  

#include<queue>  

using namespace std;  

int main()  

{  

   priority_queue<int> p;  // priority queue declaration  

   priority_queue<int> q;  // priority queue declaration  

   p.push(1); // inserting element '1' in p.  

   p.push(2); // inserting element '2' in p.  

   p.push(3); // inserting element '3' in p.  

   p.push(4); // inserting element '4' in p.  

   q.push(5); // inserting element '5' in q.  

   q.push(6); // inserting element '6' in q.  

   q.push(7); // inserting element '7' in q.  

   q.push(8); // inserting element '8' in q.  

   p.swap(q);  

   cout << "Elements of p are: " << endl;  

   while(!p.empty())  

   {  

      cout << p.top() << endl;  

       p.pop();  

   }  

   cout << "Elements of q are:" << endl;  

    while(!q.empty())  

   {  

      cout << q.top() << endl;  

       q.pop();  

   }  

    return 0;  

}

Output:

Output

Elements of p are :

8

7

6

5

Elements of q are :

4

3

2

1

Explanation

In the provided code snippet, we defined two priority queues named 'p' and 'q'. Four elements were added to the 'p' priority queue, and another four elements were added to the 'q' priority queue. Following the insertion of elements, a function called swap was employed to exchange the elements between the 'p' and 'q' queues.

Purpose of the Priority Queues

Several purposes of the priority queues in C++ are as follows:

  • Efficient Element Access: Priority queues enable constant-time (O(1)) element lookup of the most prioritized item and logarithmic (O(log n)) operations on insert and delete commands. Therefore, they excel at high-performance applications.
  • Order Management: The system performs automatic element realignment through reordering processes to keep priority intact after adding or removing entries.
  • Support for Custom Priorities: The priority queue system allows users to create their element comparison methods through custom comparator tools.
  • Useful in Real-time Processing: Real-time processing systems receive maximum benefit from using priority queues because they enable quick responses to high-priority tasks.
  • Conclusion

In summary, C++ priority queues offer developers efficient access to either the highest or lowest priority elements. By leveraging an STL priority queue, developers can construct heaps for scheduling tasks, searching systems, and managing resource allocation operations. The time complexity for adding and removing data in priority queues is O(log n), making them well-suited for applications that require high performance.

C++ Priority Queue MCQs

1) What is the default behaviour of a priority_queue in C++?

  • Returns the element with the lowest priority first
  • Stores elements in insertion order
  • Returns the element with the highest priority first
  • Returns the element with the most recent addition first

Returns the element of highest priority as the answer.

2) How can we change the default behaviour of a C++ priority_queue to access the smallest element first?

  • By using a stack instead
  • The implementation requires a Custom comparator.
  • The container requires manual sorting following each new insertion.
  • It is not possible.

3) How does a priority queue differ conceptually from a standard queue?

  • A priority queue maintains its elements inside a circular buffer structure.
  • A priority queue needs linked lists for its implementation.
  • The priority queue system eliminates elements that have low priority status.
  • A priority queue determines the sequence of element processing through priority rankings instead of arrival order.

4) Why are priority queues important in algorithm design?

  • The system uses priority queues for effective task management of priority-based items
  • They simplify pointer manipulation
  • Priority queues serve essential roles in recursive systems.
  • Priority queues enable random data storage through their mechanisms.

a) The system utilizes priority queues to efficiently manage tasks based on their priority levels.

5) What is the main purpose of the comparator in a priority queue?

  • Researchers determine queue storage capacity as the first objective.
  • The second function enables post-insertion element sorting.
  • The mechanism helps decide which elements receive priority first.
  • The third requirement establishes how to specify the container type.

c) This process aids in determining the order in which elements are given precedence.

Input Required

This code uses input(). Please provide values below:

Logic Practice
Install Logic Practice
Add to home screen for a faster app-like experience