Priority Queue in C++
Tags: cpp, dsa, algorithms, beginners
Published: 2022-11-18 06:37:07


In this article we will be exploring different methods of creating a priority queue in C++ and modifying it according to our use case.

By default priority queue in C++ implements max heap. That means that the top most element will always be the greatest of all numbers present in the priority queue.

These are some of the member functions of priority queue.
## **Member functions**
1. **Element Access**
   - **top** -> Returns the top element of the priority_queue
2. **Capacity**
   - **empty** -> returns true if empty
   - **size** -> size of priority_queue
3. **Modifiers**
   - **push** -> inserts element
   - **emplace** -> insert element  
   - **pop** -> removes the top element


## **Simple example of priority queue**

```cpp
#include <iostream>
#include <queue>

int main()
{
    std::priority_queue<int> pq;
    // inserting elements
    pq.push(1);
    pq.push(4);
    pq.push(0);

    // Printing the elements of priority queue untill the priority queue is not empty
    while (!pq.empty()) 
    {
        int top = pq.top(); // accessing the top element of priority queue
        pq.pop();           // removing the top element of the priority queue
        std::cout << top << " ";
    }

    /*
    The elements will be printed in descending order as the priority queue by default implement max-heap.
    Output : 
        4 1 0
    
    */
}
```

## **Creating a Priority Queue**

1. **Creating empty priority queue**
    ```c++
    #include <queue>
    int main()
    {
        std::priority_queue<int> pq;

    }
    ```
2. **Creating a priority queue from a vector**

    ```c++
    std::vector<int> v{5, 6, 3, 9};

    std::priority_queue<int> pq(v.begin(), v.end());
    ```
3. **Creating a min-heap priority queue**
    ```c++
    std::vector<int> v{5, 6, 3, 9};

    std::priority_queue<int, std::vector<int>, std::greater<int>> pq(v.begin(), v.end());
    ```


## **Creating priority queue with custom comparator**
In this section we will explore all sort of different techniques of creating a priority queue using our own custom comparator.

The third template parameter should be a **function pointer** or a **class with () overloaded**.

1. **Declaring a compare function**
   ```c++
    int comp(int a, int b)
    {
        return a < b;
    }

    std::vector<int> v{5, 6, 3, 9};
    //Priority queue using vector
    std::priority_queue<int, std::vector<int>, decltype(&comp)> pq(v.begin(), v.end(), comp);
    //Declaring the type of function yourself. -> bool (*)(int, int)
    std::priority_queue<int, std::vector<int>, bool (*)(int, int)> pq(v.begin(), v.end(), comp);
    //Declaring using the function class template
    std::priority_queue<int, std::vector<int>, std::function<bool(int, int)>> pq(v.begin(), v.end(), comp);

    //Empty priority queue with comp as comparator
    std::priority_queue<int, std::vector<int>, decltype(&comp)> pq2(comp);

   ```

2. **Declaring compare lambda function**  
    **NOTE :** In `decltype(comp)` we no longer require the `&` operator.
    
    ```cpp
    auto comp = [](int a, int b)
    {
        return a < b;
    };

    std::vector<int> v{5, 6, 3, 9};
    //Using decltype
    std::priority_queue<int, std::vector<int>, decltype(comp)> pq(v.begin(), v.end(), comp);
    //Using function pointer
    std::priority_queue<int, std::vector<int>, bool (*)(int, int)> pq(v.begin(), v.end(), comp);
    //Using function class template
    std::priority_queue<int, std::vector<int>, std::function<bool(int, int)>> pq(v.begin(), v.end(), comp);

    std::priority_queue<int, std::vector<int>, decltype(comp)> pq2(comp);
    ```
3. **Declaring using a compare class**  
    Declare the class like shown below.  
    **NOTE :** You can also use `struct` in place of `class`.
    ```cpp
    class Compare
    {
    public:
        bool operator()(int a, int b)
        {
            return a < b;
        }
    };
    ```
    Use the compare class while declaring the priority queue
    ```cpp
    std::priority_queue<int, std::vector<int>, Compare> pq(v.begin(), v.end());
    ```


Now lets take an example of its use case.
We want to take out students from the priority queue based on their age.

```c++
#include <iostream>
#include <queue>
#include <vector>

struct Student
{
    std::string name;
    int age;
    int rollno;

    void print()
    {
        std::cout << name << " | " << age << " | " << rollno << "\n";
    }
};

class Compare
{
public:
    bool operator()(Student &a, Student &b)
    {
        return a.age > b.age;
    }
};

int main()
{
    std::vector<Student> students{
        Student{"Naruto", 18, 100},
        Student{"Sasuke", 19, 120},
        Student{"Rock Lee", 17, 077}};

    std::priority_queue<Student, std::vector<Student>, Compare> pq(students.begin(), students.end());

    while (!pq.empty())
    {
        auto top = pq.top();
        pq.pop();
        top.print();
    }
}
#include <iostream>
#include <queue>
#include <vector>

struct Student
{
    std::string name;
    int age;
    int rollno;

    void print()
    {
        std::cout << name << " | " << age << " | " << rollno << "\n";
    }
};

class Compare
{
public:
    bool operator()(Student &a, Student &b)
    {
        return a.age > b.age;
    }
};

int main()
{
    std::vector<Student> students{
        Student{"Naruto", 18, 100},
        Student{"Sasuke", 19, 120},
        Student{"Rock Lee", 17, 077}};

    std::priority_queue<Student, std::vector<Student>, Compare> pq(students.begin(), students.end());

    while (!pq.empty())
    {
        auto top = pq.top();
        pq.pop();
        top.print();
    }
}

/* Output

Rock Lee | 17 | 63
Naruto | 18 | 100
Sasuke | 19 | 120

*/

```