【问题标题】:How to use the priority queue STL for objects?如何为对象使用优先级队列 STL?
【发布时间】:2013-11-01 08:56:32
【问题描述】:
class Person
{
public:
    int age;
};

我想将 Person 类的对象存储在优先级队列中。

priority_queue< Person, vector<Person>, ??? >

我想我需要为比较的东西定义一个类,但我不确定。

另外,当我们写作时,

priority_queue< int, vector<int>, greater<int> > 

更大的工作原理是什么?

【问题讨论】:

标签: c++ stl


【解决方案1】:

您需要为存储在队列中的类型提供有效的严格弱排序比较,在这种情况下为Person。默认使用std::less&lt;T&gt;,它解析为等同于operator&lt;。这依赖于它自己的存储类型有一个。所以如果你要实现

bool operator<(const Person& lhs, const Person& rhs); 

它应该可以在没有任何进一步更改的情况下工作。实现可以是

bool operator<(const Person& lhs, const Person& rhs)
{
  return lhs.age < rhs.age;
}

如果该类型没有自然的“小于”比较,则提供您自己的谓词而不是默认的std::less&lt;Person&gt; 会更有意义。例如,

struct LessThanByAge
{
  bool operator()(const Person& lhs, const Person& rhs) const
  {
    return lhs.age < rhs.age;
  }
};

然后像这样实例化队列:

std::priority_queue<Person, std::vector<Person>, LessThanByAge> pq;

关于使用std::greater&lt;Person&gt; 作为比较器,这将使用operator&gt; 的等效项,并具有创建优先级反转WRT 默认情况下的队列的效果。这需要存在一个可以在两个Person 实例上运行的operator&gt;

【讨论】:

  • 虽然这个答案是正确的,但我不喜欢在这里使用operator&lt;operator&lt; 实现了一个类型的默认比较,根据我的经验,这很少是你想要的。我认为迈克在他的回答中描述的方法几乎总是更可取的。
  • @BjörnPollex 同意。我正在添加一些关于此的内容。在只有一个数据成员的类中,运算符可能有意义。
  • 值得注意的是:实现bool YourClass::operator &lt;(const YourClass&amp;) const 还将允许透明地使用默认比较器std::less&lt;T&gt;。没有那么灵活,但在您需要的时候就很实用。 (和 +1)。
  • 感谢您的回答。即使类有多个成员,我也可以重载“
  • @user2441151 是的,你可以,但你必须小心逻辑。它必须实现严格的弱排序。数据成员越多,越容易出错。除非你使用std::tie,在这种情况下它是非常微不足道的。
【解决方案2】:

你会写一个比较器类,例如:

struct CompareAge {
    bool operator()(Person const & p1, Person const & p2) {
        // return "true" if "p1" is ordered before "p2", for example:
        return p1.age < p2.age;
    }
};

并将其用作比较器参数:

priority_queue<Person, vector<Person>, CompareAge>

使用greater 与默认less 的顺序相反,这意味着队列将为您提供最低值而不是最高值。

【讨论】:

  • 可以传递“比较器对象”而不是比较器类吗? (为了对其进行参数化并获得更大的灵活性)
  • @castarco 是的,您可以将特定的比较器对象作为构造函数参数传递。
  • 这是比最佳答案更可取的方法。不仅因为它实现了更高级别的比较(可以很容易地转移到其他语言中,更低和更高级别),还因为它产生了更多可重用的代码。
【解决方案3】:

优先级队列是一种抽象数据类型,它体现了容器的概念,其元素具有附加的“优先级”。最高优先级的元素总是出现在队列的前面。如果该元素被删除,则下一个最高优先级元素前进到前面。

C++标准库定义了一个类模板priority_queue,操作如下:

push:将元素插入优先队列。

top:从优先级队列中返回(不移除)最高优先级元素。

pop:从优先级队列中移除最高优先级的元素。

size:返回优先级队列中的元素个数。

empty:根据优先队列是否为空,返回true或false。

下面的代码sn-p展示了如何构造两个优先级队列,一个可以包含整数,另一个可以包含字符串:

#include <queue>

priority_queue<int> q1;
priority_queue<string> q2;

以下是优先队列使用示例:

#include <string>
#include <queue>
#include <iostream>

using namespace std;  // This is to make available the names of things defined in the standard library.

int main()
{
    piority_queue<string> pq; // Creates a priority queue pq to store strings, and initializes the queue to be empty.

    pq.push("the quick");
    pq.push("fox");
    pq.push("jumped over");
    pq.push("the lazy dog");

    // The strings are ordered inside the priority queue in lexicographic (dictionary) order:
    // "fox", "jumped over", "the lazy dog", "the quick"
    //  The lowest priority string is "fox", and the highest priority string is "the quick"

    while (!pq.empty()) {
       cout << pq.top() << endl;  // Print highest priority string
       pq.pop();                    // Remmove highest priority string
    }

    return 0;
}

这个程序的输出是:

the quick
the lazy dog
jumped over
fox

由于队列遵循优先级规则,因此字符串从最高优先级到最低优先级打印。

有时需要创建一个优先级队列来包含用户定义的对象。在这种情况下,优先级队列需要知道用于确定哪些对象具有最高优先级的比较标准。这是通过属于重载运算符 () 的类的函数对象来完成的。重载的 () 充当

struct Time {
    int h; 
    int m; 
    int s;
};

class CompareTime {
    public:
    bool operator()(Time& t1, Time& t2) // Returns true if t1 is earlier than t2
    {
       if (t1.h < t2.h) return true;
       if (t1.h == t2.h && t1.m < t2.m) return true;
       if (t1.h == t2.h && t1.m == t2.m && t1.s < t2.s) return true;
       return false;
    }
}

根据上述比较标准存储时间的优先级队列将定义如下:

priority_queue<Time, vector<Time>, CompareTime> pq;

Here is a complete program:

#include <iostream>
#include <queue>
#include <iomanip>

using namespace std;

struct Time {
    int h; // >= 0
    int m; // 0-59
    int s; // 0-59
};

class CompareTime {
public:
    bool operator()(Time& t1, Time& t2)
    {
       if (t1.h < t2.h) return true;
       if (t1.h == t2.h && t1.m < t2.m) return true;
       if (t1.h == t2.h && t1.m == t2.m && t1.s < t2.s) return true;
       return false;
    }
};

int main()
{
    priority_queue<Time, vector<Time>, CompareTime> pq;

    // Array of 4 time objects:

    Time t[4] = { {3, 2, 40}, {3, 2, 26}, {5, 16, 13}, {5, 14, 20}};

    for (int i = 0; i < 4; ++i)
       pq.push(t[i]);

    while (! pq.empty()) {
       Time t2 = pq.top();
       cout << setw(3) << t2.h << " " << setw(3) << t2.m << " " <<
       setw(3) << t2.s << endl;
       pq.pop();
    }

    return 0;
}

程序从最晚到最早打印时间:

5  16  13
5  14  20
3   2  40
3   2  26

如果我们希望最早的时间具有最高优先级,我们将像这样重新定义 CompareTime:

class CompareTime {
public:
    bool operator()(Time& t1, Time& t2) // t2 has highest prio than t1 if t2 is earlier than t1
    {
       if (t2.h < t1.h) return true;
       if (t2.h == t1.h && t2.m < t1.m) return true;
       if (t2.h == t1.h && t2.m == t1.m && t2.s < t1.s) return true;
       return false;
    }
};

【讨论】:

  • 我有一个问题,如果可以的话。 priority_queue,比较时间> pq; .为什么第二个参数 vector
  • 哦,不……狐狸不是棕色的,非棕色的狐狸跳过(跳)在懒惰的狗身上。 :-(
  • 第一个 sn-p 中的 pq.front() 不应该是 pq.top() 吗?
【解决方案4】:

这段代码可能会有所帮助..

#include <bits/stdc++.h>
using namespace std;    

class node{
public:
    int age;
    string name;
    node(int a, string b){
        age = a;
        name = b;
    }
};

bool operator<(const node& a, const node& b) {

    node temp1=a,temp2=b;
    if(a.age != b.age)
        return a.age > b.age;
    else{
        return temp1.name.append(temp2.name) > temp2.name.append(temp1.name);
    }
}

int main(){
    priority_queue<node> pq;
    node b(23,"prashantandsoon..");
    node a(22,"prashant");
    node c(22,"prashantonly");
    pq.push(b);
    pq.push(a);
    pq.push(c);

    int size = pq.size();
    for (int i = 0; i < size; ++i)
    {
        cout<<pq.top().age<<" "<<pq.top().name<<"\n";
        pq.pop();
    }
}

输出:

22 prashantonly
22 prashant
23 prashantandsoon..

【讨论】:

    【解决方案5】:

    我们可以定义用户定义的比较器:。下面的代码对你有帮助。

    代码片段:

    #include<bits/stdc++.h>
    using namespace std;
    
    struct man
    {
      string name;
      int priority; 
    };
    
    class comparator
    {
     public:
       bool operator()(const man& a, const man& b)
       {
            return a.priority<b.priority;
       }
    };
    
    int main()
    {
       man arr[5];
       priority_queue<man, vector<man>, comparator> pq;
    
       for(int i=0; i<3; i++)
       {
         cin>>arr[i].name>>arr[i].priority;
         pq.push(arr[i]);
       }
    
       while (!pq.empty())
       {
         cout<<pq.top().name<<" "<<pq.top().priority;
         pq.pop();
         cout<<endl;
       }
       return 0;
    }
    

    输入:

    蝙蝠侠 2
    悟空 9
    马里奥 4

    输出

    悟空 9
    马里奥 4
    蝙蝠侠 2

    【讨论】:

      猜你喜欢
      • 2016-04-13
      • 1970-01-01
      • 2012-07-20
      • 2016-03-10
      • 1970-01-01
      • 2013-03-16
      • 1970-01-01
      • 2014-10-18
      相关资源
      最近更新 更多