问题
I want to create a priority queue for which I am using a heap(using array).The priority queue will be generic thus accept all data types as long as the client pass a compare function through constructor to compare the two types.
How can I create a constructor that will accept the compare function as a parameter? Moreover how can I make the compare function to be called when I check
return (Type a==Type b)
Eg.
struct node{
string val1;
string val2;
vector<node *> connectedNodes;
};
int compareNode(node a,node b){
//describe the compare
}
int main(){
PQueue<node> q(compareNode);
}
The PQueue class is implemented as an array. As the adding,bubbling-up, heapifying needs to compare two ValType I want them to compare using compareNode.
回答1:
You don't have to do this: don't use an array, use the built-in priority-queue of the STL library in c++. It has its own compare function which you can alter.
Reference: http://www.cplusplus.com/reference/queue/priority_queue/
You can also see topcoder tutorials (for algorithmic usage).
回答2:
Let me first give you a simple answer and then a more versatile one.
You can simply pass a function as parameter by declaring the type of that parameter to be the type of pointer function. You can also have variables of type pointer to function. For instance, if the declaration of your function is
int compareNode(node a, node b)
then you could do something like this:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
struct node{
string val1;
string val2;
vector<node *> connectedNodes;
};
int compareNode(node a,node b){
//describe the compare
return a.val2.compare(b.val2); // or any other code
}
template <class T>
class PQueue {
protected:
// this declares a protected member named compareFunction of type pointer to a function which takes 2 T parameters and returns a int. Note that all the parenthesis are mandatory
int (*compareFunction)(T, T);
public:
PQueue (int (*compareFunctionParameter)(T, T)) : compareFunction(compareFunctionParameter) {
// this constructor receives a pointer to function and initializes it's member to that pointer. If the constructor initialization list confuses you, you can read 'compareFunction = compareFunctionParameter '
}
int someMethod() {
// call the function through the pointer you have:
node n1, n2;
n1.val1 = "node1_val1";
n1.val2 = "zzz";
n2.val1 = "node2_val1";
n2.val2 = "aaa";
return compareFunction(n1, n2);
}
};
int main() {
PQueue<node> pq(compareNode);
cout << pq.someMethod() << endl;
return 0;
}
http://ideone.com/EPjbya
Hope this you can use this.
Now to the more versatile example.
C++11 introduces lambdas. http://www.cprogramming.com/c++11/c++11-lambda-closures.html http://www.stroustrup.com/C++11FAQ.html#lambda
#include <iostream>
#include <vector>
#include <string>
#include <functional>
using namespace std;
struct node{
string val1;
string val2;
vector<node *> connectedNodes;
};
int compareNode(node a,node b){
//describe the compare
return a.val2.compare(b.val2); // or any other code
}
template <class T, class Comparator>
class PQueue {
protected:
Comparator compareFunction;
public:
PQueue (Comparator compareFunctionParameter) : compareFunction(compareFunctionParameter) {
}
int someMethod() {
// call the function
node n1, n2;
n1.val1 = "node1_val1";
n1.val2 = "zzz";
n2.val1 = "node2_val1";
n2.val2 = "aaa";
return compareFunction(n1, n2);
}
};
int main() {
// queue with pointer to function
PQueue<node, int (*)(node, node)> pq(compareNode);
cout << pq.someMethod() << endl;
// queue with lamda (anonimous function)
PQueue<node, std::function<int (node, node)>> pq_lambda([](node a, node b) -> int {return a.val1.compare(b.val1);} );
cout << pq_lambda.someMethod() << endl;
return 0;
}
http://ideone.com/ryQmAn You need to compile this code for C++11 standard.
Here the template Comparator can be both pointer to function and lambda. If you are interested in lambdas, the two links I provided above should get you started.
来源:https://stackoverflow.com/questions/17512705/passing-compare-function-for-a-generic-class