简体   繁体   中英

std::priority_queue compare and the age of queue elements

Taken from here http://www.cplusplus.com/reference/queue/priority_queue/

Compare
A binary predicate that takes two elements (of type T) as arguments and returns a bool.
The expression comp(a,b), where comp is an object of this type and a and b are elements in the container, shall return true if a is considered to go before b in the strict weak ordering the function defines.

When writing a compare function is there any way of telling which element has been waiting in the queue longer?

Assuming the compare function is called whenever a new element is to be inserted, will 'a' always be the new item and 'b' be an element already in the queue? Or does it work differently?

My idea was that something like this:

bool my_class::operator()(const my_class &a, const my_class &b) {
    //Lower priority comes first
    return (a.get_priority() < b.get_priority());
}

When the priority of 'a' and 'b' are the same then 'b' is given priority because it has been in the queue longer.

Thankyou for any feedback on how std::queue works and how I might achieve my goal.

Assuming the compare function is called whenever a new element is to be inserted, will 'a' always be the new item and 'b' be an element already in the queue? Or does it work differently?

As Dietmar Kühl noted below, there is no guarantee when the predicate is that the arguments are ordered in any relation to order in which the elements are inserted.

When the priority of 'a' and 'b' are the same then 'b' is given priority because it has been in the queue longer.

Use something like this:

static unsigned long count = 0;
std::priority_queue<std::pair<my_class,unsigned long>> queue;

When you insert item into a queue, insert the previous count also and increment it:

queue.push(std::make_pair(obj, count++));

Now the count can be used as a "timestamp", so just do that in your compare function.

class MyComparator{
public:  
  bool operator()(const std::pair<my_class,unsigned long>& a, const std::pair<my_class,unsigned long>& b)  const
    {
       if (a.first == b.first)
          return a.second < b.second;
       return a.first < b.first;
    }
};

Here is a small example:

#include <queue>
#include <utility>
#include <vector>
#include <iostream>


class MyComparator{
    public:
      bool operator()(const std::pair<int,unsigned long>& a, const std::pair<int,unsigned long>& b)
        {
           if (a.first == b.first)
              return b.second  < a.second;
           return a.first < b.first;
        }
    };

unsigned long count = 0;
int main()
{
        std::priority_queue<std::pair<int,unsigned long>, std::vector<std::pair<int, unsigned long> >, MyComparator> queue;

        queue.push(std::make_pair(4, count++));
        queue.push(std::make_pair(4, count++));
        queue.push(std::make_pair(5, count++));
        queue.push(std::make_pair(3, count++));

        while(queue.size() > 0)
        {
                std::cout << "[" << queue.top().first << ", " << queue.top().second << "]" << std::endl;
                queue.pop();
        }

        return 0;

}

The output:

[5, 2]
[4, 0]
[4, 1]
[3, 3]

Keep a timestamp for the objects, and set it when the object is inserted into the queue. Then just use that timestamp as part of the condition for your comparison.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM