Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ordering issue while popping from priority_queue, Is this a bug with std::priority_queue

#include <functional>
#include <queue>
#include <vector>
#include <iostream>

 struct Temp
 {
   int p;
   std::string str;
 };

 struct TempCompare
 {
     bool operator()(Temp const & a, Temp const & b)
     {
         return a.p > b.p;
     }
 };

int main() {

    std::priority_queue<Temp, std::vector<Temp>, TempCompare> pq;
    //Enable and Disable the following line to see the different output
    //{Temp t; t.p=8;t.str="str1";pq.push(t);} 
    {Temp t; t.p=8;t.str="str2";pq.push(t);}
    {Temp t; t.p=9; t.str="str1";pq.push(t);}
    {Temp t; t.p=9; t.str="str2";pq.push(t);}

    while(!pq.empty())
    {
        std::cout << pq.top().p << " " << pq.top().str << std::endl;
        pq.pop();
    }
}

Run the above program with enabling and disabling the fourth line in main; The output you get when its disabled is

8 str2
9 str1
9 str2

whereas when its enabled you get

8 str1
8 str2
9 str2
9 str1

Shouldnt the behavior be consistent?

like image 512
rkb Avatar asked Jan 30 '23 22:01

rkb


1 Answers

No. There is no reason for the behaviour to be consistent. Temp{9, "str1"} and Temp{9,"str2"} are equal according to your comparison function, so they get returned in an arbitrary order. Adding different elements to the queue is quite likely to change that order.

If you want them returned in a consistent order, you need to extend the comparison function. The simplest way is

     bool operator()(Temp const & a, Temp const & b)
     {
         return std::tie(a.p,a.str) > std::tie(b.p,b.str);
     }

If you want "descending in p, but ascending in str", you'll have to do it yourself.

like image 145
Martin Bonner supports Monica Avatar answered Feb 08 '23 16:02

Martin Bonner supports Monica