I'm trying to declare a priority_queue of nodes, using bool Compare(Node a, Node b) as the comparator function (which is outside the node class).
What I currently have is:
priority_queue<Node, vector<Node>, Compare> openSet;
For some reason, I'm getting Error: "Compare" is not a type name
Changing the declaration to priority_queue <Node, vector<Node>, bool Compare>
gives me Error: expected a '>'
I've also tried:
priority_queue<Node, vector<Node>, Compare()> openSet;
priority_queue<Node, vector<Node>, bool Compare()> openSet;
priority_queue<Node, vector<Node>, Compare<Node, Node>> openSet;
How should I correctly declare my priority_queue?
11 Answers
Note - You may also want to check other answers, especially the one with decltype and lambda
You should declare a class Compare and overload operator() for it like this:
class Foo
{
};
class Compare
{
public:
bool operator() (Foo, Foo)
{
return true;
}
};
int main()
{
std::priority_queue<Foo, std::vector<Foo>, Compare> pq;
return 0;
}
Or, if you for some reasons can't make it as class, you could use std::function for it:
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;
}
The accepted answer shows how to use a class or a std::function as comparator. We can also pass a function pointer, as cute_ptr's answer already showed. However, the syntax to do so is much simpler than shown there:
class Node;
bool Compare(Node a, Node b);
std::priority_queue<Node, std::vector<Node>, decltype(&Compare)> openSet(Compare);
That is, there is no need to explicitly encode the function's type, you can let the compiler do that for you using decltype.
This is very useful if the comparator is a lambda. You cannot specify the type of a lambda in any other way than using decltype. For example:
auto compare = [](Node a, Node b) { return a.foo < b.foo; }
std::priority_queue<Node, std::vector<Node>, decltype(compare)> openSet(compare);
The third template parameter must be a class who has operator()(Node,Node) overloaded.
So you will have to create a class this way:
class ComparisonClass {
public:
bool operator() (Node, Node) {
//comparison code here
}
};
And then you will use this class as the third template parameter like this:
priority_queue<Node, vector<Node>, ComparisonClass> q;
Answering your question directly:
I'm trying to declare a
priority_queueof nodes, usingbool Compare(Node a, Node b) as the comparator functionWhat I currently have is:
priority_queue<Node, vector<Node>, Compare> openSet;For some reason, I'm getting Error:
"Compare" is not a type name
The compiler is telling you exactly what's wrong: Compare is not a type name, but an instance of a function that takes two Nodes and returns a bool.
What you need is to specify the function pointer type:
std::priority_queue<Node, std::vector<Node>, bool (*)(Node, Node)> openSet(Compare)
You have to define the compare first. There are 3 ways to do that:
- use class
- use struct (which is same as class)
- use lambda function.
It's easy to use class/struct because easy to declare just write this line of code above your executing code
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)
}
};
Calling code:
priority_queue<Node,vector<Node>,compare> pq;
One can also use a lambda function.
auto Compare = [](Node &a, Node &b) { //compare };
std::priority_queue<Node, std::vector<Node>, decltype(Compare)> openset(Compare);
In case this helps anyone :
static bool myFunction(Node& p1, Node& p2) {}
priority_queue <Node, vector<Node>, function<bool(Node&, Node&)>> pq1(myFunction);
In the priority queue, there is a predefined boolean function "operator<()", try to overload this function as per your requirement.
bool operator<(const Node& x,const Node& y){
return x.data>y.data;
}
priority_queue<Node> min_heap;
With latest c++ standard, you can actually declare a lambda function for comparator which would make the code much cleaner. Here is a sample code:
#include <queue>
class Foo
{
public:
int i;
};
int main()
{
auto comparator = [](const Foo& a, const Foo& b) {
return a.i > b.i;
};
std::priority_queue<Foo, std::vector<Foo>, decltype(comparator)> pq(comparator);
return 0;
}
prefer struct, and it's what std::greater do
struct Compare {
bool operator()(Node const&, Node &) {}
}
With the help of struct also we can do this. The code will go something like below.
struct myCompare{
bool operator()(Node &a, Node &b){
// Your own custom logic to compare the two nodes and return a boolean value.
}
}
priority_queue<Node, vector<Node>, myCompare> openSet;