带有指针和比较器的优先级队列
Priority queue with Pointers and Comparator C++
我刚开始学习c++,一半的时间我不知道我在做什么,花了几个小时在谷歌上搜索,盲目地把代码放在我的项目中,这可能是一个基本的问题,但我似乎不能得到它的权利。
这是我的作业的要求,我需要有这些:
public:
bool operator()(Edge*, Edge*)
图类中的
private:
priority_queue<Edge*, vector<Edge*>, Edge> edges
我在声明priority_queue时有问题。细节:
如果我直接使用这些,边缘类会给我一个"必须有类的参数"的错误,我知道我不能将两个指针重载到bool操作符中,所以这就是我所尝试的:
in the Edge.cpp:
#include "Edge.h"
using namespace std;
Edge::Edge(Vertex* s, Vertex* d, double w)
{
source = s;
destination = d;
weight = w;
}
double Edge::getWeight()
{
return weight;
}
struct CompareWeight : public std::binary_function<Edge*, Edge*, bool>
{
bool operator()(Edge* e1,Edge* e2)
{
double w1 = e1->getWeight();
double w2 = e2->getWeight();
if(w1>w2){
return true;
}
else {
return false;
}
}
};
^我甚至不确定在类中放入结构是否正确,加上在这个原因中我不知道在我的Edge.h文件中放入什么。
in the Edge.h:
#include "Vertex.h"
class Edge
{
public:
Edge(Vertex*, Vertex*, double);
double getWeight();
friend struct CompareWeight; // ??? does not seems right
private:
Vertex* source;
Vertex* destination;
double weight;
}
至于图形类是真正的问题所在,我甚至不能通过声明优先级队列而不得到一个错误。
图中
#include "Vertex.h"
#include "Edge.h"
#include <vector>
#include <queue>
class Graph
{
public:
...
private:
priority_queue<Edge*, vector<Edge*>, Edge> edges
// This give pointer error: no match for call to '(Edge) (Edge*&, Edge*&)'
}
第二次尝试:
// same as above
private:
priority_queue<Edge*, vector<Edge*>, CompareWeight> edges
// This give error: 'CompareWeight' not declared in this scope
我不知道为什么第一个错误,但第二个错误我明白它很清楚,但我不知道如何修复它,我应该把一些东西在前面的比较重量?我试了很多方法,都没用。
任何帮助将非常感激!否则我这门课可能会不及格。第一次问在stackoverflow,如果我做错了什么,请告诉我。
您要求将bool operator()(Edge*, Edge*)
实现为Edge
类的常规成员是可能的,但很少这样做。
比较器有以下习惯风格,所有必须为所处理的序列中包含的对象提供严格的弱排序:
- 独立函子类
- 单机
operator <
过载 - 对象类成员
operator <
过载。 < - 独立函数/gh>静态类函数
- 静态类函子类
这个列表上的第五个(5)是最接近的事情,看起来像他们的指令是试图做的,但它是从来没有实现为operator()
。作为Edge
的成员,可以执行(1),但是要这样做,Edge
类型必须支持默认构造。我将在一分钟内解释如何做到这一点。在上面列出的选项中,对于这个特定情况,性能(内联的可能性)和实现便利性的最佳候选选项是(1)和(6)。如果您的队列保存实际的Edge
对象而不是Edge
指针(3)将是一个自然的适合,并提供良好的性能。
对于有序容器和容器适配器(如优先级队列),比较器的作用是比较符合严格弱排序的两个项。如果你不知道那是什么,请看这个链接。在实现中,它归结为:if, 且仅当 x < y
返回true,否则返回false。这意味着必须执行以下内容:
-
x < x
总是返回false - 如果
x < y
返回true,则y < x
必须返回false - 如果
x < y
和y < x
都返回false,则x
等于y
类边缘/strong>
class Edge
{
public:
Edge(Vertex* src, Vertex* dst, double w)
: source(src), destination(dst), weight(w)
{
};
// note: const-ness
double getWeight() const { return weight; }
Vertex const* getSource() const { return source; }
Vertex* getSource() { return source; }
Vertex const* getDestination() const { return destination; }
Vertex* getDestination() { return destination; }
private:
Vertex* source;
Vertex* destination;
double weight;
};
类CmpEdgePtrs
struct CmpEdgePtrs
{
bool operator()(const Edge* lhs, const Edge* rhs) const
{
return lhs->getWeight() < rhs->getWeight();
}
};
类图表strong>
class Graph
{
// rest of class stuff
private:
priority_queue<Edge*, vector<Edge*>, CmpEdgePtrs> edges;
};
老实说,这是对共享智能指针使用的尖叫,但我把它留给你。上面的代码很有可能在实现优先级队列逻辑的标准库算法的整个使用位置内联比较器,并且在给定指针容器的约束条件下,这样的性能很有可能是最优的。
完成分配的需求
这个可以完全在类Edge
中完成,因为它毕竟只是一个类类型。作为优先级队列适配器的模板参数传递的第三种类型是公开bool operator()
的类型,没有什么可以阻止您让Edge
的实例为您做这件事。这很奇怪,但它仍然可以通过一些修改来工作:
首先,将bool operator()(const Edge*, const Edge*) const
移动到声明为public的Edge
类中。其次,为Edge
提供默认构造函数,因为在创建函子来执行比较时,优先级队列的内部算法将需要它。
class Edge
{
public:
// regular parameterized construction
Edge(Vertex* src, Vertex* dst, double w)
: source(src), destination(dst), weight(w)
{
};
// ADDED: allows parameterless initialization
Edge()
: source(), designation(), weight()
{}
// note: const-ness
double getWeight() const { return weight; }
Vertex const* getSource() const { return source; }
Vertex* getSource() { return source; }
Vertex const* getDestination() const { return destination; }
Vertex* getDestination() { return destination; }
// ADDED: used when an instance of `Edge` is used as comparator functor
bool operator ()(const Edge* lhs, const Edge* rhs) const
{
return lhs->weight < rhs->weight;
}
private:
Vertex* source;
Vertex* destination;
double weight;
};
class Graph
{
// rest of class stuff
private:
// NOTE: uses Edge-type as the functor type that will
// deliver the comparison of Edge pointers.
priority_queue<Edge*, vector<Edge*>, Edge> edges;
};
这是非常不寻常的,但它的好处是允许函子直接访问被比较的Edge
对象的成员变量,而不是通过公共getter和setter或必须将比较器添加为友。但它也有缺点。除了
Edge
对象。
简而言之,这样做几乎没有什么好处,并且在不正确使用所需代码时存在潜在问题,因此,我建议使用第一个选项。
祝你好运
你错过的东西叫做前向声明。在Edge.h中,只允许在一行中单独写class Vertex;
。在这行之后,c++知道存在这样一个类,因此Vertex *
是一个指针(而不是乘法的前半部分)。
[编辑]这个前向声明取代了Edge.h中的#include "Vertex.h"
。
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 按对象的特定方法按升序排列的C++优先级队列
- 使用2个键的cpp-stl::优先级队列排序不正确
- 为什么我需要C++中不同的排序格式来对这个USACO代码上的数组和优先级队列进行排序
- 打印优先级队列
- 带自定义比较器的最小优先级队列
- 优先级队列自定义比较器
- 排序数组优先级队列
- 更改运行时优先级队列的排序功能
- 优先级队列构造函数的工作
- 实现优先级队列
- 优先级队列功能比较
- 在C++中打印对的优先级队列的所有值时出现问题
- 使用堆的优先级队列,具有相同键的值不遵循 FIFO(先进先出)
- 为什么某些 STL 容器(堆栈、队列、优先级队列)不支持迭代器?
- 是否可以使用简单队列创建优先级队列
- 如何在 c++ 中创建对的优先级队列.这会弹出具有最小值的元素.默认的弹出最大值
- Cython中带有自定义比较器的优先级队列
- 优先级队列比较器[C++].
- asio::io_service 具有多个线程的优先级队列处理