可能是一个非常新的C ++问题。假设我有一个类,顶点,有几个属性和方法。我想把一堆顶点填充到一个队列中,并让它们按顶点类的特殊属性排序(为学校做一个基本的Dijkstra图算法)。
然而,我遇到了一些渗透C ++语法的问题。这是我的代码(顶点未显示,但它非常简单)。
typedef std::priority_queue<benchmark::vertex*,
std::vector<benchmark::vertex*>,
std::less<benchmark::vertex*> > q_type;
q_type* q = new q_type();
benchmark::vertex* v1 = new benchmark::vertex(0.1,0.1);
v1->cost = 4;
benchmark::vertex* v2 = new benchmark::vertex(0.1,0.1);
v2->cost = 8;
benchmark::vertex* v3 = new benchmark::vertex(0.1,0.1);
v3->cost = 6;
benchmark::vertex* v4 = new benchmark::vertex(0.1,0.1);
v4->cost = 10;
benchmark::vertex* v5 = new benchmark::vertex(0.1,0.1);
v5->cost = 2;
q->push(v1);
q->push(v2);
q->push(v3);
q->push(v4);
q->push(v5);
while (!q->empty()) {
std::cout << (*(q->top())).cost << std::endl;
q->pop();
}
在本地计算机上输出2,10,6,8,4。我正在使用GCC(gcc版本4.3.3(Ubuntu 4.3.3-5ubuntu4))的Linux机器上测试它。显然,我希望它按顺序吐出数字。
如何制作比较器,以便在进行比较时查看并比较vertex.cost?
答案 0 :(得分:9)
用任何带有两个顶点指针作为参数的函数或函子替换std::less<benchmark::vertex*>
,如果第一个参数属于第二个参数,则返回true
。
std::less<benchmark::vertex*>
将比较两个指针,因此您看到的结果显示了它们在内存中的顺序。
答案 1 :(得分:5)
std::less<benchmark::vertex*>
比较地址而不是顶点
// Functor
struct VertexLess
{
bool operator (const benchmark::vertex* left, const benchmark::vertex* right) const {
return left->id < right->id;
}
};
typedef std::priority_queue<benchmark::vertex*,
std::vector<benchmark::vertex*>,
VertexLess > q_type;
答案 2 :(得分:1)
Alexey Malistov回答的额外模板版本:
template <class T, class M, const M T::*member>
struct MemberGenericDereferenceLess
{
bool operator()(const T* lhs, const T* rhs) const
{
return ((*lhs).*member < (*rhs).*member);
}
};
typedef std::priority_queue<benchmark::vertex*,
std::vector<benchmark::vertex*>,
MemberGenericDereferenceLess<benchmark::vertex,
int,
&benchmark::vertex::cost> > q_type;
我认为你只需要第一个和第三个模板参数,但我无法通过几分钟的黑客攻击来推断class M
。 (为读者锻炼)
这样做的好处是您可以快速更改您排序的成员。假设你的vertex
看起来像......
namespace benchmark
{
struct vertex
{
vertex(double a_, double b_) : a(a_), b(b_) {}
double a;
double b;
int cost;
};
}
您可以在a
或b
上输入typedef:
typedef std::priority_queue<benchmark::vertex*,
std::vector<benchmark::vertex*>,
MemberGenericDereferenceLess<benchmark::vertex,
double,
&benchmark::vertex::a> > q_type;
typedef std::priority_queue<benchmark::vertex*,
std::vector<benchmark::vertex*>,
MemberGenericDereferenceLess<benchmark::vertex,
double,
&benchmark::vertex::b> > q_type;
这是一个可以玩的小驱动程序:
#include <iostream>
#include <queue>
#include <vector>
namespace benchmark
{
struct vertex
{
vertex(double a_, double b_) : a(a_), b(b_) {}
double a;
double b;
int cost;
};
}
template <class T, class M, const M T::*member>
struct MemberGenericDereferenceLess
{
bool operator()(const T* lhs, const T* rhs) const
{
return ((*lhs).*member < (*rhs).*member);
}
};
int main(int argc, char** argv)
{
typedef std::priority_queue<benchmark::vertex*,
std::vector<benchmark::vertex*>,
MemberGenericDereferenceLess<benchmark::vertex,
int,
&benchmark::vertex::cost> > q_type;
q_type q;
benchmark::vertex* v1 = new benchmark::vertex(0.1,0.1);
v1->cost = 4;
benchmark::vertex* v2 = new benchmark::vertex(0.1,0.1);
v2->cost = 8;
benchmark::vertex* v3 = new benchmark::vertex(0.1,0.1);
v3->cost = 6;
benchmark::vertex* v4 = new benchmark::vertex(0.1,0.1);
v4->cost = 10;
benchmark::vertex* v5 = new benchmark::vertex(0.1,0.1);
v5->cost = 2;
q.push(v1);
q.push(v2);
q.push(v3);
q.push(v4);
q.push(v5);
while(q.empty() == false)
{
std::cout << q.top()->cost << std::endl;
q.pop();
}
// Clean up all of those new()s
delete v1;
delete v2;
delete v3;
delete v4;
delete v5;
std::cin.get();
return 0;
}