Home C++ C++ Standard Template Library (STL) priority_queue tutorial

C++ Standard Template Library (STL) priority_queue tutorial

The priority_queue in the C++ Standard Template Library (STL) is a container adapter that provides a convenient way to manage a collection of elements with priority.

It is based on the heap data structure, typically a max-heap by default, where the largest element is given the highest priority. You can customize it to function as a min-heap as well.

Key Features of priority_queue

  1. Max-Heap by Default: The largest element has the highest priority.
  2. Min-Heap Option: Custom comparators can be used to make it behave as a min-heap.
  3. Efficient Operations: Provides push, pop, and top operations with logarithmic complexity.

Basic Syntax

#include <queue>
using namespace std;

priority_queue<Type> pq;             // Max-heap (default)
priority_queue<Type, vector<Type>, Comparator> pq; // Min-heap with custom comparator

Let’s explore the priority_queue with examples of both max-heap and min-heap configurations.

1. Basic Max-Heap priority_queue

By default, priority_queue in C++ is a max-heap, where the largest element has the highest priority.

#include <iostream>
#include <queue>
using namespace std;

int main() {
    // Declare a max-heap priority_queue
    priority_queue<int> pq;

    // Insert elements
    pq.push(10);
    pq.push(20);
    pq.push(5);

    // Display top element (largest element)
    cout << "Top element: " << pq.top() << endl;

    // Remove elements and display them
    cout << "Elements in priority order: ";
    while (!pq.empty()) {
        cout << pq.top() << " ";
        pq.pop();
    }
    cout << endl;

    return 0;
}

Output:

Top element: 20
Elements in priority order: 20 10 5 

2. Using priority_queue as a Min-Heap

To use priority_queue as a min-heap, specify greater<Type> as the comparator.

#include <iostream>
#include <queue>
#include <vector>
using namespace std;

int main() {
    // Declare a min-heap priority_queue
    priority_queue<int, vector<int>, greater<int>> pq;

    // Insert elements
    pq.push(10);
    pq.push(20);
    pq.push(5);

    // Display top element (smallest element)
    cout << "Top element: " << pq.top() << endl;

    // Remove elements and display them
    cout << "Elements in priority order: ";
    while (!pq.empty()) {
        cout << pq.top() << " ";
        pq.pop();
    }
    cout << endl;

    return 0;
}

Output:

Top element: 5
Elements in priority order: 5 10 20 

3. Custom Comparator with priority_queue

You can use a custom comparator for complex sorting requirements, such as creating a max-heap or min-heap for pairs.

#include <iostream>
#include <queue>
#include <vector>
using namespace std;

// Custom comparator for min-heap of pairs based on the second element
struct Compare {
    bool operator()(pair<int, int> a, pair<int, int> b) {
        return a.second > b.second;
    }
};

int main() {
    priority_queue<pair<int, int>, vector<pair<int, int>>, Compare> pq;

    // Insert elements (pairs)
    pq.push({1, 50});
    pq.push({2, 30});
    pq.push({3, 40});

    // Display top element (pair with smallest second value)
    cout << "Top element: {" << pq.top().first << ", " << pq.top().second << "}" << endl;

    // Remove elements and display them
    cout << "Elements in priority order based on second value: ";
    while (!pq.empty()) {
        auto elem = pq.top();
        cout << "{" << elem.first << ", " << elem.second << "} ";
        pq.pop();
    }
    cout << endl;

    return 0;
}

Output:

Top element: {2, 30}
Elements in priority order based on second value: {2, 30} {3, 40} {1, 50} 

4. Checking if priority_queue is Empty

The empty function checks if the priority_queue is empty.

#include <iostream>
#include <queue>
using namespace std;

int main() {
    priority_queue<int> pq;

    // Check if the priority queue is empty
    if (pq.empty()) {
        cout << "The priority queue is empty." << endl;
    }

    // Insert an element and check again
    pq.push(10);
    if (!pq.empty()) {
        cout << "The priority queue is not empty." << endl;
    }

    return 0;
}

Output:

The priority queue is empty.
The priority queue is not empty.

5. Retrieving the Size of a priority_queue

Use the size function to get the number of elements in the priority_queue.

#include <iostream>
#include <queue>
using namespace std;

int main() {
    priority_queue<int> pq;

    // Insert elements
    pq.push(10);
    pq.push(20);
    pq.push(5);

    // Display the size of the priority queue
    cout << "Size of the priority queue: " << pq.size() << endl;

    return 0;
}

Output:

Size of the priority queue: 3

6. Using priority_queue with Custom Objects

You can use priority_queue with custom objects by providing a custom comparator to define their priority.

#include <iostream>
#include <queue>
#include <string>
using namespace std;

// Custom structure for tasks
struct Task {
    string name;
    int priority;

    // Custom comparator for min-heap based on priority
    bool operator<(const Task &other) const {
        return priority > other.priority;
    }
};

int main() {
    priority_queue<Task> pq;

    // Insert tasks
    pq.push({"Task 1", 3});
    pq.push({"Task 2", 1});
    pq.push({"Task 3", 2});

    // Display tasks in priority order
    cout << "Tasks in priority order:" << endl;
    while (!pq.empty()) {
        Task t = pq.top();
        cout << t.name << " (Priority: " << t.priority << ")" << endl;
        pq.pop();
    }

    return 0;
}

Output:

Tasks in priority order:
Task 2 (Priority: 1)
Task 3 (Priority: 2)
Task 1 (Priority: 3)

7. Modifying a priority_queue with Existing Elements

Since priority_queue doesn’t support random access, you’ll need to empty it, modify elements, and reinsert them if you want to change existing elements.

#include <iostream>
#include <queue>
#include <vector>
using namespace std;

int main() {
    priority_queue<int> pq;

    // Insert elements
    pq.push(10);
    pq.push(20);
    pq.push(5);

    // Modify elements by removing and reinserting them
    vector<int> elements;
    while (!pq.empty()) {
        int val = pq.top();
        pq.pop();
        elements.push_back(val * 2);  // Double each element
    }

    // Reinsert modified elements
    for (int val : elements) {
        pq.push(val);
    }

    // Display modified elements in priority order
    cout << "Modified elements in priority order: ";
    while (!pq.empty()) {
        cout << pq.top() << " ";
        pq.pop();
    }
    cout << endl;

    return 0;
}

Output:

Modified elements in priority order: 40 20 10 

8. Using priority_queue with Strings

You can use priority_queue to manage strings based on lexicographical order.

#include <iostream>
#include <queue>
#include <string>
using namespace std;

int main() {
    // Max-heap for strings
    priority_queue<string> pq;

    // Insert strings
    pq.push("apple");
    pq.push("orange");
    pq.push("banana");

    // Display strings in priority order (lexicographical order)
    cout << "Strings in priority order: ";
    while (!pq.empty()) {
        cout << pq.top() << " ";
        pq.pop();
    }
    cout << endl;

    return 0;
}

Output:

Strings in priority order: orange banana apple 

9. Using a priority_queue for Sorting an Array

You can use a priority_queue to sort an array by inserting all elements and removing them in priority order.

#include <iostream>
#include <queue>
#include <vector>
using namespace std;

int main() {
    vector<int> arr = {10, 3, 15, 7, 8};

    // Min-heap to sort in ascending order
    priority_queue<int, vector<int>, greater<int>> pq;

    // Insert elements into the priority queue
    for (int num : arr) {
        pq.push(num);
    }

    // Extract sorted elements
    cout

 << "Sorted elements: ";
    while (!pq.empty()) {
        cout << pq.top() << " ";
        pq.pop();
    }
    cout << endl;

    return 0;
}

Output:

Sorted elements: 3 7 8 10 15 

Summary Table of priority_queue Operations

Operation Code Example Description
Initialize Max-Heap priority_queue<int> pq; Initializes a max-heap (default)
Initialize Min-Heap priority_queue<int, vector<int>, greater<int>> pq; Initializes a min-heap
Insert Element pq.push(10); Inserts an element
Access Top Element pq.top(); Accesses the highest priority element
Remove Top Element pq.pop(); Removes the highest priority element
Check if Empty pq.empty(); Checks if the priority_queue is empty
Get Size pq.size(); Returns the number of elements
Custom Comparator priority_queue<Type, vector<Type>, Compare> pq; Initializes with a custom comparator
Clear All Elements Use pq.pop() in a loop Clears all elements manually
Use with Custom Objects struct Task {…}; and priority_queue<Task> pq; Use a struct with custom comparator

Complete Example

This example demonstrates initializing a max-heap and a min-heap, inserting elements, accessing and removing elements, and using a custom comparator.

#include <iostream>
#include <queue>
#include <vector>
using namespace std;

// Custom comparator for min-heap of pairs based on the second element
struct Compare {
    bool operator()(pair<int, int> a, pair<int, int> b) {
        return a.second > b.second;
    }
};

int main() {
    // Max-heap
    priority_queue<int> maxHeap;
    maxHeap.push(10);
    maxHeap.push(20);
    maxHeap.push(5);

    cout << "Max-Heap: ";
    while (!maxHeap.empty()) {
        cout << maxHeap.top() << " ";
        maxHeap.pop();
    }
    cout << endl;

    // Min-heap
    priority_queue<int, vector<int>, greater<int>> minHeap;
    minHeap.push(10);
    minHeap.push(20);
    minHeap.push(5);

    cout << "Min-Heap: ";
    while (!minHeap.empty()) {
        cout << minHeap.top() << " ";
        minHeap.pop();
    }
    cout << endl;

    // Min-heap with custom comparator for pairs
    priority_queue<pair<int, int>, vector<pair<int, int>>, Compare> pairPQ;
    pairPQ.push({1, 50});
    pairPQ.push({2, 30});
    pairPQ.push({3, 40});

    cout << "Custom Comparator Min-Heap for Pairs: ";
    while (!pairPQ.empty()) {
        auto elem = pairPQ.top();
        cout << "{" << elem.first << ", " << elem.second << "} ";
        pairPQ.pop();
    }
    cout << endl;

    return 0;
}

Sample Output:

Max-Heap: 20 10 5 
Min-Heap: 5 10 20 
Custom Comparator Min-Heap for Pairs: {2, 30} {3, 40} {1, 50} 

Key Takeaways

  • priority_queue is a heap-based container that defaults to a max-heap.
  • Custom comparators make it versatile for both max-heap and min-heap use cases.
  • Useful for scenarios where elements need to be processed in a priority order, such as implementing queues with custom priorities, sorting, or maintaining top elements.

You may also like