The std::priority_queue
container adapter is a max-queue construct. It utilizes a "less" comparator to sort the queued items in a way where the maximum item is always first. Thus, if you want to have the smallest items first, you need a comparator that does the opposite of what may first seem natural to you.
A quick example, suppose you had a vector of int
values and you wanted them prioritized largest to smallest. This is the natural, default operational action of std::priority_queue<int>
. it uses std::less<int>
to determine the order of the items (which come before, which come after), and given those outcomes, ensures the largest appears first in the queue. Consider the following example, which makes two int
queues, one which uses std::less<int>
the other std::greater<int>
for comparison:
#include <iostream>
#include <algorithm>
#include <queue>
#include <random>
int main()
{
std::random_device rd;
std::mt19937 rng(rd());
std::uniform_int_distribution<> dist(1,10);
std::priority_queue<int, std::vector<int>, std::less<int>> q1;
std::priority_queue<int, std::vector<int>, std::greater<int>> q2;
for (int i=0; i<20; ++i)
{
int value = dist(rng);
q1.push(value);
q2.push(value);
}
std::cout << "q1: ";
for (; !q1.empty(); q1.pop())
std::cout << q1.top() << ' ';
std::cout << '\n';
std::cout << "q2: ";
for (; !q2.empty(); q2.pop())
std::cout << q2.top() << ' ';
std::cout << '\n';
}
Output (varies)
q1: 10 10 8 8 8 7 6 6 5 5 5 4 4 4 3 3 3 2 1 1
q2: 1 1 2 3 3 3 4 4 4 5 5 5 6 6 7 8 8 8 10 10
As you can see, a queue that uses a "greater" comparator for its less-op when determining ordering delivers what you seek. We just need to fit such a thing into your queue and its Event
type
You need a comparator that does the opposite of the default ordering:
#include <iostream>
#include <algorithm>
#include <queue>
class Event
{
public:
enum EvtType { arrival_1, arrival_2, arrival_3, arrival_4, arrival_5, arrival_6 };
Event(EvtType type = arrival_1, double etime = 0.0)
: _type(type)
, _etime(etime)
{}
EvtType get_Type() const { return _type; };
double get_Time() const { return _etime; }
protected:
EvtType _type;
double _etime;
};
struct EventLess
{
bool operator()(const Event& lhs, const Event& rhs) const
{
return (lhs.get_Time() > rhs.get_Time());
}
};
int main()
{
std::priority_queue<Event, std::vector<Event>, EventLess> q;
q.push(Event(Event::arrival_1, 3.0));
q.push(Event(Event::arrival_2, 2.0));
q.push(Event(Event::arrival_3, 1.0));
q.push(Event(Event::arrival_1, 1.0));
q.push(Event(Event::arrival_2, 2.0));
q.push(Event(Event::arrival_3, 3.0));
while (!q.empty())
{
const Event& e = q.top();
std::cout << e.get_Type() << ' ' << e.get_Time() << '\n';
q.pop();
}
}
Output
2 1
0 1
1 2
1 2
0 3
2 3
Note the time value (the second) is ordered smallest to largest. This is because our comparator EventLess
says "items with larger times are 'less' than items with smaller times", and the queue naturally pushes those down the queue rather than promoting them to the top. What makes this work is simply this:
struct EventLess
{
bool operator()(const Event& lhs, const Event& rhs) const
{
return (lhs.get_Time() > rhs.get_Time());
}
};
Here we're telling the caller (the queue adapter) that given two elements, the one with a greater time value should be considered "less" than something with a smaller time value. The queue then orders the items largest to smallest.
I think you understand the need for custom comparison. I just don't think you understood how the std::priority_queue
works. It's a max-queue. You just have to convince it your definition of max
is something different.