我有一项任务是使用Dijkstra的最短路径算法进行简单的网络模拟。编码实现的一部分是我不理解的,它给了我悲伤。 我搜索了堆栈溢出,发现了许多关于Dijkstra的有用的问题,但没有我的具体问题。如果我没有彻底研究,我会道歉。
我使用Mark Allen Weiss在C ++中的数据结构和算法分析中的伪代码:
void Graph::dijkstra( Vertex s)
{
for each Vertex v
{
v.dist = INFINITY;
v.known = false;
}
s.dist = 0;
while( there is an unknown distance vertex )
{
Vertex v = smallest unknown distance vertex;
v.known = true;
for each Vertex w adjacent to v
{
if (!w.known)
{
int cvw = cost of edge from v to w;
if(v.dist + cvw < w.dist)
{
//update w
decrease(w.dist to v.dist + cvw);
w.path = v;
}
}
}
}
我的实现似乎与上一个if
语句不同。
if(v.dist + cvw < w.dist)
我的代码永远不会进入下面的内容,因为每个节点的距离都被初始化为(基本上)无穷大,算法似乎永远不会改变距离。因此,比较的左侧不会小于右侧。我怎么会误解这个?
这是我的(杂乱的)代码:
class Vertex
{
private:
int id;
unordered_map < Vertex*, int > edges;
int load_factor;
int distance;
bool known;
public:
//getters and setters
};
void dijkstra(Vertex starting_vertex)
{
for (int i = 0; i < vertices.size(); i++)
{
//my program initially stores vertices in the vertex in spot (id - 1).
if (vertices[i].get_id() == starting_vertex.get_id())
{
vertices[i].set_distance(0);
vertices[i].set_known(true);
}
else
{
vertices[i].set_distance(10000000);
vertices[i].set_known(false);
}
}
for (int i = 0; i < vertices.size(); i++)
{
//while there is an unknown distance vertex
if (vertices[i].is_known() == false)
{
vertices[i].set_known(true);
//for every vertex adjacent to this vertex
for (pair<Vertex*, int> edge : vertices[i].get_edges())
{
//if the vertex isn't known
if (edge.first->is_known() == false)
{
//calculate the weight using Adam's note on dijkstra's algorithm
int weight = edge.second * edge.first->get_load_factor();
if (vertices[i].get_distance() + weight < edge.first->get_distance())
//this is my problem line. The left side is never smaller than the right.
{
edge.first->set_distance(vertices[i].get_distance() + weight);
path.add_vertex(edge.first);
}
}
}
}
}
}
谢谢!
答案 0 :(得分:1)
你错过了这一步:
Vertex v = smallest unknown distance vertex;
而是循环遍历所有顶点。
到起始顶点的距离初始化为0
,因此如果您实现算法的这一部分并选择距离最小但不是“已知”的v
,您将从启动开始顶点和if
应该有效。
替换:
for (int i = 0; i < vertices.size(); i++)
{
//while there is an unknown distance vertex
if (vertices[i].is_known() == false)
{
...
}
}
有类似的东西:
while(countNumberOfUnknownVertices(vertices) > 0)
{
Vertex& v = findUnknownVertexWithSmallestDistance(vertices);
...
}
答案 1 :(得分:0)
你错过了Dijkstra算法的两个重要部分。
实施
while( there is an unknown distance vertex )
{
Vertex v = smallest unknown distance vertex;
将v设置为您来到的第一个未知顶点。它应该是所有未知顶点,距离最小的那个。
另一个错误是,不是在顶点上进行一次传递,而是在找到的每个未知顶点上做一些工作,而是需要在完成工作后再次搜索。
例如,如果在一次迭代中从顶点5向外扩展,则可能使顶点3成为距离最小的新未知顶点。你不能从5继续搜索。
除非您开发一些数据结构(可能是Heap)以快速进行搜索,否则搜索距离最远的未知顶点将会很慢。来吧,现在进行线性搜索。 Dijkstra的算法仍然有效,但它需要时间O(N ^ 2)。您应该能够将其降低到至少O(N log N)。