在 C++ 中创建一个包含不同类型事件的最小优先级队列
Posted
技术标签:
【中文标题】在 C++ 中创建一个包含不同类型事件的最小优先级队列【英文标题】:Create a Min Priority Queue contain different types of event in C++ 【发布时间】:2016-07-29 11:01:30 【问题描述】:class Event
// Overloading the comparison operators
friend bool operator < (const Event& e1, const Event& e2);
friend bool operator == (const Event& e1, const Event& e2);
public:
Event() ;
enum EvtType arrival_1, arrival_2, arrival_3, arrival_4, arrival_5, arrival_6;
Event(EvtType type, double etime):
_type(type), _etime(etime)
EvtType get_Type()
return _type;
double get_time()
return _etime;
protected:
EvtType _type;
double _etime;
;
bool operator < (const Event& e1, const Event& e2)
return e2._etime < e1._etime;
bool operator == (const Event& e1, const Event& e2)
if(e1._etime != e2._etime)return false;
if(e1._type == (Event::arrival_2 && Event::arrival_3 && Event::arrival_4 && Event::arrival_5 && Event::arrival_6)) return true;
return false;
priority_queue <Event> FEL;
我创建了一个名为“Event”的类,其中包含几种类型的事件和发生的时间。在此之后,我想创建一个优先级队列“FEL”来包含这些事件及其时间。但是,一般来说,优先级队列总是对事件库的所有最大值进行排序。
如何根据最小值对这些事件进行排序,这样当我调用 FEL.top() 时,我会得到时间最短的事件。
我试图通过使用 bool 运算符来解决这个问题。但是它仍然有问题。任何人请帮助解决此问题将不胜感激。
非常感谢
【问题讨论】:
std::priority_queue
允许您传递任何比较器函数。它可以是默认的std::less
,也可以是像std::greater
这样的其他标准比较器,甚至可以是自定义函数或可调用对象。
有没有办法使用bool操作符来设置,所以每次调用FEL.top()时,都会自动获取时间最短的事件?请给我演示一些代码。
是的,通过为您的 Event
类实现 operator<
函数。这就是你所要做的。
***.com/questions/16111337/…
【参考方案1】:
std::priority_queue
容器适配器是一个最大队列结构。它利用“较少”比较器以 最大 项始终排在第一位的方式对排队的项进行排序。因此,如果您想首先获得 最小 项,则需要一个与您最初看起来自然相反的比较器。
举个简单的例子,假设您有一个包含int
值的向量,并且您希望它们的优先级最大 到最小。这是std::priority_queue<int>
的自然默认操作操作。它使用std::less<int>
来确定项目的顺序(哪些在前面,哪些在后面),并在给定这些结果的情况下确保最大的首先出现在队列中。考虑以下示例,它创建了两个int
队列,一个使用std::less<int>
,另一个使用std::greater<int>
进行比较:
#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';
输出(可变)
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
如您所见,在确定排序时使用“更大”比较器作为其较少操作的队列会交付您所寻求的。我们只需要将这样的东西放入您的队列及其Event
类型
您需要一个与默认顺序相反的比较器:
#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();
输出
2 1
0 1
1 2
1 2
0 3
2 3
注意时间值(秒)从小到大排列。这是因为我们的比较器EventLess
说“时间较大的项目比时间较小的项目‘少’”,并且队列自然地将它们推到队列的下方,而不是将它们提升到顶部。使这项工作发挥作用的原因很简单:
struct EventLess
bool operator()(const Event& lhs, const Event& rhs) const
return (lhs.get_Time() > rhs.get_Time());
;
这里我们告诉调用者(队列适配器)给定两个元素,一个具有更大时间值的元素应该被认为“小于”具有更小的时间值的元素。然后队列将项目从大到小排序。
我认为您了解自定义比较的必要性。我只是认为您不了解std::priority_queue
的工作原理。这是一个最大队列。你只需要说服它你对max
的定义是不同的。
【讨论】:
非常感谢。这很有帮助。现在我对优先队列有了更多的了解。 @Rocky 如果这回答了您的问题,请使用勾号将其标记为已接受的答案。如果没有,请说明人们还能做些什么来提供帮助。【参考方案2】:首先,您不能仅根据显示的代码创建std::priority_queue<Event>
。 Event
没有实现 <
运算符,而 std::priority_queue<Event>
需要它。
您要么定义了 <
运算符,但它未包含在显示的代码中,要么您必须已经将一个可选的比较器类传递给现有的 std::priority_queue
,它为所有 @987654327 指定了严格的弱排序@s.
在任何一种情况下,只需更改适当的比较函数,即可按照您想要的顺序比较您的Event
s。
【讨论】:
【参考方案3】:您可以向std::priority_queue
提供自定义比较器类型参数。
但在我们这样做之前,让我们为您的 Event
类定义运算符 >
:
bool Event::operator>(Event const& other)
return _etime > other._etime;
您也可以按照与其他运算符相同的方式定义它。现在,您的队列类型变为:
std::priority_queue<Event, std::vector<Event>, std::greater<Event>> FEL;
这将具有将具有最低时间戳_etime
的Event
对象放在顶部的效果。
【讨论】:
以上是关于在 C++ 中创建一个包含不同类型事件的最小优先级队列的主要内容,如果未能解决你的问题,请参考以下文章