使用自定义比较器在c ++中声明priority_queue

Ste*_*rad 61 c++ std priority-queue

我试图声明一个priority_queue of nodes,bool Compare(Node a, Node b)用作比较器函数(在节点类之外).

我现在拥有的是:

priority_queue<Node, vector<Node>, Compare> openSet;
Run Code Online (Sandbox Code Playgroud)

出于某种原因,我得到了 Error: "Compare" is not a type name

将声明更改为 priority_queue <Node, vector<Node>, bool Compare>

给我 Error: expected a '>'

我也尝试过:

priority_queue<Node, vector<Node>, Compare()> openSet;
priority_queue<Node, vector<Node>, bool Compare()> openSet;
priority_queue<Node, vector<Node>, Compare<Node, Node>> openSet; 
Run Code Online (Sandbox Code Playgroud)

我应该如何正确地宣布我的priority_queue

awe*_*oon 82

你应该为它声明一个类Compare和重载operator(),如下所示:

class Foo
{

};

class Compare
{
public:
    bool operator() (Foo, Foo)
    {
        return true;
    }
};

int main()
{
    std::priority_queue<Foo, std::vector<Foo>, Compare> pq;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

或者,如果由于某些原因无法将其作为类,您可以使用std::function它:

class Foo
{

};

bool Compare(Foo, Foo)
{
    return true;
}

int main()
{
    std::priority_queue<Foo, std::vector<Foo>, std::function<bool(Foo, Foo)>> pq(Compare);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 我不断地回到这个答案,现在可能已经有 50 次了,我永远记不起语法 (7认同)
  • @StevenMorad,我更喜欢使用带有重载`operator()`的类,它看起来更简单. (2认同)
  • @soon 为什么我们要重载运算符 () ?这是否与priority_queues 在内部实现的方式有关?重载 &gt; 或 &lt; 在直觉上是有意义的,但 () 运算符没有那么多 (2认同)
  • @Piyush,问题是将自定义比较器传递给`pritority_queue`.根据问题,可以重载`operator <`并使用内置的`std :: less`比较器,然而,`bool Compare(节点a,节点b)`在类`Node`之外声明. (2认同)
  • @Piyush using () 的语法是将一个函数作为参数传递给另一个函数,而不是具体的运算符。这也称为函子。请参阅此链接:https://en.wikipedia.org/wiki/Function_object (2认同)

Cri*_*ngo 18

接受的答案让你相信你必须使用一个类或一个std::function比较器.这不是真的!cute_ptr的答案显示了如何将函数传递给构造函数,但有一种更简单的方法:

class Node;
bool Compare(Node a, Node b);

std::priority_queue<Node, std::vector<Node>, decltype(&Compare)> openSet(Compare);
Run Code Online (Sandbox Code Playgroud)

也就是说,不需要显式编码函数的类型,您可以让编译器为您执行此操作.

  • 这太棒了,我想知道这里是否有任何潜在的陷阱(问题)。希望看到这个答案得到更多的关注和讨论。 (3认同)

Mic*_*Mic 13

第三个模板参数必须是已operator()(Node,Node)超载的类.所以你必须这样创建一个类:

class ComparisonClass {
    bool operator() (Node, Node) {
        //comparison code here
    }
};
Run Code Online (Sandbox Code Playgroud)

然后你将使用这个类作为第三个模板参数,如下所示:

priority_queue<Node, vector<Node>, ComparisonClass> q;
Run Code Online (Sandbox Code Playgroud)

  • 运算符方法必须是公共的. (8认同)

小智 7

您必须先定义比较。有3种方法可以做到这一点:

  1. 使用类
  2. 使用结构(与类相同)
  3. 使用 lambda 函数。

使用 class/struct 很容易,因为很容易声明只需在执行代码上方编写这行代码

struct compare{
  public:
  bool operator()(Node& a,Node& b) // overloading both operators 
  {
      return a.w < b.w: // if you want increasing order;(i.e increasing for minPQ)
      return a.w > b.w // if you want reverse of default order;(i.e decreasing for minPQ)
   }
};
Run Code Online (Sandbox Code Playgroud)

调用代码:

priority_queue<Node,vector<Node>,compare> pq;
Run Code Online (Sandbox Code Playgroud)


cut*_*ptr 6

直接回答你的问题:

我正在尝试声明一个priority_queue节点,使用bool Compare(Node a, Node b) as the comparator function

我现在拥有的是:

priority_queue<Node, vector<Node>, Compare> openSet;
Run Code Online (Sandbox Code Playgroud)

出于某种原因,我收到错误:

"Compare" is not a type name
Run Code Online (Sandbox Code Playgroud)

编译器正在告诉你究竟出了什么问题:Compare不是类型名称,而是一个带两个Nodes并返回a 的函数实例bool.
你需要的是指定函数指针类型:
std::priority_queue<Node, std::vector<Node>, bool (*)(Node, Node)> openSet(Compare)


bor*_*ree 6

还可以使用 lambda 函数。

auto Compare = [](Node &a, Node &b) { //compare };
std::priority_queue<Node, std::vector<Node>, decltype(Compare)> openset(Compare);
Run Code Online (Sandbox Code Playgroud)


Maz*_*MIK 5

如果这对任何人有帮助:

static bool myFunction(Node& p1, Node& p2) {}
priority_queue <Node, vector<Node>, function<bool(Node&, Node&)>> pq1(myFunction);
Run Code Online (Sandbox Code Playgroud)