declaring a priority_queue in c++ with a custom comparator
C++StdPriority QueueC++ Problem Overview
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
?
C++ Solutions
Solution 1 - C++
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;
}
Solution 2 - C++
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);
Solution 3 - C++
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;
Solution 4 - C++
Answering your question directly:
> I'm trying to declare a priority_queue
of nodes, using bool Compare(Node a, Node b) as the comparator function
>
> What I currently have is:
>
> priority_queue
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)
Solution 5 - C++
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;
Solution 6 - C++
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);
Solution 7 - C++
In case this helps anyone :
static bool myFunction(Node& p1, Node& p2) {}
priority_queue <Node, vector<Node>, function<bool(Node&, Node&)>> pq1(myFunction);
Solution 8 - C++
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;
Solution 9 - C++
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;
}
Solution 10 - C++
prefer struct, and it's what std::greater do
struct Compare {
bool operator()(Node const&, Node &) {}
}
Solution 11 - C++
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;