134

The default stl priority queue is a Max one (Top function returns the largest element).

Say, for simplicity, that it is a priority queue of int values.

mechanical_meat
  • 163,903
  • 24
  • 228
  • 223
amitlicht
  • 2,868
  • 6
  • 23
  • 27

9 Answers9

226

Use std::greater as the comparison function:

std::priority_queue<int, std::vector<int>, std::greater<int> > my_min_heap;
James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • and if it is not priority queue of ints, but some MyClass object? – amitlicht Mar 13 '10 at 17:43
  • 6
    @eriks You have some options. Either your class defines `operator>`, which would work like charm with `std::greater`. You could write your own functor also instead of `std::greater` if you like. – Khaled Alshaya Mar 13 '10 at 17:45
  • 3
    @AraK, I think you mean `operator<` ;) – Peter Alexander Mar 13 '10 at 17:46
  • 1
    @Poita_ Doesn't `std::greater` use `operator>` and `std::less` use `operator<`? Sorry if I am missing something. – Khaled Alshaya Mar 13 '10 at 17:48
  • 1
    @AraK, @Poita_: Yes, `std::greater` uses `operator>`. @eriks: What AraK said above is the correct way to do this for user-defined types. – James McNellis Mar 13 '10 at 17:53
  • The default comparison functor is less, so logically, to reverse the order, you would use greater. – David Smith Mar 21 '10 at 14:40
  • @JamesMcNellis Would it be incorrect to write greater() in place of greater ? Can you please tell me the difference between the two? – piyukr Feb 25 '15 at 08:47
  • 8
    Why do we have to add vector ?? wouldn't it be obvious, as we already said we want int? What other options are there for the second parameter? –  Jan 16 '16 at 19:12
  • 4
    @CarryonSmiling in the standard template library, the `vector` and `deque` classes fulfill the requirements that an underlying container must meet for a priority_queue. You can also use a custom container class. You can find a much elaborate explanation on http://www.cplusplus.com/reference/queue/priority_queue/ – Tanmay Garg Jun 03 '16 at 13:14
  • 8
    Can someone explain why does min heap uses greater not less ? – Telenoobies Aug 12 '18 at 00:54
  • 1
    @Telenoobies relevant quote from [C++ reference](https://en.cppreference.com/w/cpp/container/priority_queue): "Note that the Compare parameter is defined such that it returns `true` if its first argument comes *before* its second argument in a weak ordering. But because the priority queue outputs largest elements first, the elements that "come before" are actually output last. That is, the front of the queue contains the "last" element according to the weak ordering imposed by Compare." – Leonid Vasilev Jun 18 '20 at 14:57
  • 2
    Since C++ 14, you can use `std::greater<>` instead. This will default to `std::greater` and deduce the actual compared type for you. – Escape0707 Sep 11 '20 at 11:41
  • @Telenoobies It's a little confusing but think of the compare function to return `true` when you want to put the element at the bottom of the priority queue, and `false` to put the element at the top of the priority queue. Since default implementation is std::less, that will put the smallest element at the bottom of the priority queue and therefore the largest element is at the top (max heap). To create a min heap we use `std::greater` which puts the largest element at the bottom and smallest element at the top (min heap). – Marlon Dec 11 '21 at 18:10
53

One way would be to define a suitable comparator with which to operate on the ordinary priority queue, such that its priority gets reversed:

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

 struct compare  
 {  
   bool operator()(const int& l, const int& r)  
   {  
       return l > r;  
   }  
 };  

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

     pq.push(3);  
     pq.push(5);  
     pq.push(1);  
     pq.push(8);  
     while ( !pq.empty() )  
     {  
         cout << pq.top() << endl;  
         pq.pop();  
     }  
     cin.get();  
 }

Which would output 1, 3, 5, 8 respectively.

Some examples of using priority queues via STL and Sedgewick's implementations are given here.

AndyUK
  • 3,933
  • 7
  • 42
  • 44
  • 1
    Can you please explain why we use l>r and not l – Dhruv Mullick Aug 02 '14 at 07:25
  • 3
    The default comparator for the priority queue is lr or r – Diaa Nov 14 '14 at 10:44
  • 1
    @AndyUK Hello, ¿why you use a struct for implement the comparation operator? thanks in advance – AER Nov 08 '18 at 18:21
  • 1
    The default priority queue in C++ is a max priority queue. – qwr Feb 20 '20 at 08:03
  • @DhruvMullick as qwr said, by default the PQ is max priority queue and the comparator used is less<> so in order to get the min PQ you need to reverse that by using greater<> or l>r. – Saurabh Rana Nov 23 '20 at 20:28
  • 1
    @DhruvMullick It's a little confusing but think of the compare function to return `true` when you want to put the element at the bottom of the priority queue, and `false` to put the element at the top of the priority queue. Since default implementation is std::less, that will put the smallest element at the bottom of the priority queue and therefore the largest element is at the top (max heap). To create a min heap we use `std::greater` which puts the largest element at the bottom and smallest element at the top (min heap). – Marlon Dec 11 '21 at 18:08
  • @AER It is common to use structs for functors that will be passed to STL algorithms. You could use a class as well if you want, it doesn't matter too much. The significant difference is that, structs by default have all its member as “public”, and class by default have all its member “private”. – AndyUK Jan 06 '22 at 11:53
34

The third template parameter for priority_queue is the comparator. Set it to use greater.

e.g.

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

You'll need #include <functional> for std::greater.

Peter Alexander
  • 53,344
  • 14
  • 119
  • 168
33

You can do it in multiple ways:
1. Using greater as comparison function :

 #include <bits/stdc++.h>

using namespace std;

int main()
{
    priority_queue<int,vector<int>,greater<int> >pq;
    pq.push(1);
    pq.push(2);
    pq.push(3);

    while(!pq.empty())
    {
        int r = pq.top();
        pq.pop();
        cout<<r<< " ";
    }
    return 0;
}

2. Inserting values by changing their sign (using minus (-) for positive number and using plus (+) for negative number :

int main()
{
    priority_queue<int>pq2;
    pq2.push(-1); //for +1
    pq2.push(-2); //for +2
    pq2.push(-3); //for +3
    pq2.push(4);  //for -4

    while(!pq2.empty())
    {
        int r = pq2.top();
        pq2.pop();
        cout<<-r<<" ";
    }

    return 0;
}

3. Using custom structure or class :

struct compare
{
    bool operator()(const int & a, const int & b)
    {
        return a>b;
    }
};

int main()
{

    priority_queue<int,vector<int>,compare> pq;
    pq.push(1);
    pq.push(2);
    pq.push(3);

    while(!pq.empty())
    {
        int r = pq.top();
        pq.pop();
        cout<<r<<" ";
    }

    return 0;
}

4. Using custom structure or class you can use priority_queue in any order. Suppose, we want to sort people in descending order according to their salary and if tie then according to their age.

    struct people
    {
        int age,salary;

    };
    struct compare{
    bool operator()(const people & a, const people & b)
        {
            if(a.salary==b.salary)
            {
                return a.age>b.age;
            }
            else
            {
                return a.salary>b.salary;
            }

    }
    };
    int main()
    {

        priority_queue<people,vector<people>,compare> pq;
        people person1,person2,person3;
        person1.salary=100;
        person1.age = 50;
        person2.salary=80;
        person2.age = 40;
        person3.salary = 100;
        person3.age=40;


        pq.push(person1);
        pq.push(person2);
        pq.push(person3);

        while(!pq.empty())
        {
            people r = pq.top();
            pq.pop();
            cout<<r.salary<<" "<<r.age<<endl;
    }
  1. Same result can be obtained by operator overloading :

    struct people
    {
    int age,salary;
    
    bool operator< (const people & p)const
    {
        if(salary==p.salary)
        {
            return age>p.age;
        }
        else
        {
            return salary>p.salary;
        }
    }};
    

    In main function :

    priority_queue<people> pq;
    people person1,person2,person3;
    person1.salary=100;
    person1.age = 50;
    person2.salary=80;
    person2.age = 40;
    person3.salary = 100;
    person3.age=40;
    
    
    pq.push(person1);
    pq.push(person2);
    pq.push(person3);
    
    while(!pq.empty())
    {
        people r = pq.top();
        pq.pop();
        cout<<r.salary<<" "<<r.age<<endl;
    }
    
Taohidul Islam
  • 5,246
  • 3
  • 26
  • 39
23

In C++11 you could also create an alias for convenience:

template<class T> using min_heap = priority_queue<T, std::vector<T>, std::greater<T>>;

And use it like this:

min_heap<int> my_heap;
mechatroner
  • 1,272
  • 1
  • 17
  • 25
8

One Way to solve this problem is, push the negative of each element in the priority_queue so the largest element will become the smallest element. At the time of making pop operation, take the negation of each element.

#include<bits/stdc++.h>
using namespace std;

int main(){
    priority_queue<int> pq;
    int i;

// push the negative of each element in priority_queue, so the largest number will become the smallest number

    for (int i = 0; i < 5; i++)
    {
        cin>>j;
        pq.push(j*-1);
    }

    for (int i = 0; i < 5; i++)
    {
        cout<<(-1)*pq.top()<<endl;
        pq.pop();
    }
}
PAVAN BANSAL
  • 127
  • 1
  • 3
3

Based on above all answers I created an example code for how to create priority queue. Note: It works C++11 and above compilers

#include <iostream>
#include <vector>
#include <iomanip>
#include <queue>

using namespace std;

// template for prirority Q
template<class T> using min_heap = priority_queue<T, std::vector<T>, std::greater<T>>;
template<class T> using max_heap = priority_queue<T, std::vector<T>>;

const int RANGE = 1000;

vector<int> get_sample_data(int size);

int main(){
  int n;
  cout << "Enter number of elements N = " ; cin >> n;
  vector<int> dataset = get_sample_data(n);

  max_heap<int> max_pq;
  min_heap<int> min_pq;

  // Push data to Priority Queue
  for(int i: dataset){
    max_pq.push(i);
    min_pq.push(i);
  }

  while(!max_pq.empty() && !min_pq.empty()){
    cout << setw(10) << min_pq.top()<< " | " << max_pq.top() << endl;
    min_pq.pop();
    max_pq.pop();
  }

}


vector<int> get_sample_data(int size){
  srand(time(NULL));
  vector<int> dataset;
  for(int i=0; i<size; i++){
    dataset.push_back(rand()%RANGE);
  }
  return dataset;
}

Output of Above code

Enter number of elements N = 4

        33 | 535
        49 | 411
       411 | 49
       535 | 33
ajayramesh
  • 3,576
  • 8
  • 50
  • 75
2

We can do this using several ways.

Using template comparator parameter

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

      pq.push(40);
      pq.push(320);
      pq.push(42);
      pq.push(65);
      pq.push(12);

      cout<<pq.top()<<endl;
      return 0;
    }

Using used defined compartor class

     struct comp
     {
        bool operator () (int lhs, int rhs)
        {
           return lhs > rhs;
        }
     };

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

       pq.push(40);
       pq.push(320);
       pq.push(42);
       pq.push(65);
       pq.push(12);

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

       return 0;
    }
rashedcs
  • 3,588
  • 2
  • 39
  • 40
2

Multiply values with -1 and use max heap to get the effect of min heap

Akash
  • 54
  • 4