创建最小优先级队列在C ++中包含不同类型的事件

时间:2016-07-29 11:01:30

标签: c++

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;

我创建了一个名为&#34; Event&#34;其中包含几种类型的事件和时间。在此之后,我想创建一个优先级队列&#34; FEL&#34;包含这些事件和他们的时代。但是,通常优先级队列总是将事件基数排序为所有最大值。

如何根据最小值对这些事件进行排序,这样当我调用FEL.top()时,我将以最短的时间获取事件。

我试图通过使用bool运算符来解决这个问题。但它仍有问题。任何人都有帮助解决这个问题会很感激。

非常感谢

3 个答案:

答案 0 :(得分: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的定义是不同的。

答案 1 :(得分:0)

您无法首先根据显示的代码创建std::priority_queue<Event>Event未实现<所需的std::priority_queue<Event>运算符。

您要么定义了<运算符,但它没有包含在显示的代码中,或者您必须已经将可选的比较器类传递给现有的std::priority_queue,它指定严格的弱顺序所有Event s。

在任何一种情况下,只需更改相应的比较功能,即可按您想要的顺序比较Event

答案 2 :(得分:0)

您可以为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;

这样可以将Event对象的最低时间戳_etime放在最上面。