C++中的Dijkstra算法
Dijkstra's algorithm in C++
我需要通过ADT图实现Dijkstra的算法,使用邻接矩阵表示,通过使用C/c++语言增强下面的伪代码来寻找最短路径。
procedure Dijkstra(G, w, r, Parent[0:n-1], Dist)
for v← 0 to n-1 do
Dist[v] ← ∞
InTheTree[v] ← .false.
endfor
Parent[r] ←-1
Dist[r] ←0
for Stage ←1 to n-1 do
Select vertex u that minimises Dist[u] over all u such that InTheTree[u] = .false.
InTheTree[u] = .true. // add u to T
for each vertex v such that uv ∈ E do // update Dist[v] and
if .not. InTheTree[v] then // Parent[v] arrays
if Dist[u] + w(uv) < Dist[v]
Dist[v] = Dist[u] + w(uv)
Nearest[v] ←w(uv)
Parent[v] ← u
endif
endif
endfor
endfor
end Dijkstra
这是我的代码的解决方案,正在用c++编码。我的讲师声称代码不符合伪代码的要求,我不确定哪里出了问题,谁能帮我找出代码和伪代码之间不匹配的地方?
#include <stdio.h>
#include <limits.h>
#define N 9
int minDistance(int dist[], bool sptSet[])
{
int min = INT_MAX, min_index;
for (int n = 0; n < N; n++)
if (sptSet[v] == false && dist[n] <= min)
min = dist[n], min_index = n;
return min_index;
}
int printSolution(int dist[], int v)
{
printf("Vertex Distance from Sourcen");
for (int i = 0; i < N; i++)
printf("%d tt %dn", i, dist[i]);
}
void dijkstra(int graph[N][N], int src)
{
int dist[N];
bool sptSet[N];
for (int i = 0; i < N; i++) {
dist[i] = INT_MAX;
sptSet[i] = false;
}
dist[src] = 0;
for (int count = 0; count < N-1; count++)
{
int u = minDistance(dist, sptSet);
sptSet[u] = true;
for (int n = 0; n < N; n++)
if (!sptSet[n] && graph[u][n] && dist[u] != INT_MAX
&& dist[u]+graph[u][n] < dist[n])
dist[n] = dist[u] + graph[u][n];
}
printSolution(dist, N);
}
int main()
{
int graph[N][N] = {{0, 4, 0, 0, 0, 0, 0, 8, 0},
{4, 0, 8, 0, 0, 0, 0, 11, 0},
{0, 8, 0, 7, 0, 4, 0, 0, 2},
{0, 0, 7, 0, 9, 14, 0, 0, 0},
{0, 0, 0, 9, 0, 10, 0, 0, 0},
{0, 0, 4, 0, 10, 0, 2, 0, 0},
{0, 0, 0, 14, 0, 2, 0, 1, 6},
{8, 11, 0, 0, 0, 0, 1, 0, 7},
{0, 0, 2, 0, 0, 0, 6, 7, 0}
};
dijkstra(graph, 0);
return 0;
}
最明显的不匹配是您的代码没有任何与伪代码的Parent
数组相对应的内容。我把它作为一个输出参数,尽管它没有明确地这样标记。正如你似乎已经认识到的,它不需要只计算最小路径的长度,但它包含了这些路径中实际步骤的所有信息,而这些信息通常是需要的。
你也没有伪代码的Nearest
的类比;但是,抱怨这一点有点意味,因为Nearest
不是例程的参数,并且伪代码没有显示其元素被读取。因此,它似乎没有任何有用的目的。
似乎这段代码也不完全匹配:
if (!sptSet[n] && graph[u][n] && dist[u] != INT_MAX
&& dist[u]+graph[u][n] < dist[n])
dist[n] = dist[u] + graph[u][n];
条件&& dist[u] != INT_MAX
不对应于伪代码中的任何内容。(这也是不必要的,因为u
是由minDistance()
返回的,因此该条件应该总是满足的)。
可以想象,您的指导老师也可能不满意您打印最小路径长度而不是返回它们。它有点依赖于伪代码方言,但我倾向于把参数列表中Dist
的出现作为它是一个输出参数的指示,而不仅仅是一个内部变量。
如果你的老师非常挑剔,那么也许你可以通过指出伪代码中一些明显的错误来得到一些松懈:
- 如前所述,
- 看起来条件
if Dist[u] ← w(uv) < Dist[v] then
应该改为if Dist[u] + w(uv) < Dist[v] then
。(您已经实现了正确的版本,这可能被解释为与伪代码的另一个差异。) - 看起来
Parent[r] ← u
应该是Parent[v] ← u
。
Nearest
不是一个参数,它被写入,但从不从中读取。当然,也可能是你的导师希望你准确地实现伪代码,错误和所有....
作为策略问题,我会尝试使用更好地匹配伪代码的变量名。我不认为老师以这些理由拒绝这些代码是公平的,但是比较c++代码和伪代码对于每个人来说会更容易一些,如果你能更接近你的名字的话。
当我在谈论你的代码时,顺便说一下,我注意到虽然你的minDistance()
函数似乎实现了伪代码的需求,但它是以一种低效的方式实现的(而且Dijkstra一开始就不是特别高效)。通常的方法是使用最小堆来跟踪已经看到但尚未访问的节点,这减少了从O(n)到O(log n)选择最小距离节点的成本。当然,对于您正在测试的元素很少,这并不重要,但对于大型图,差异是巨大的。
问题是我相信你的minDistance函数,似乎你只更新未访问的节点(第10行如果(sptSet[v] == false &&Dist [n] <= min))。我想这是错的。考虑下面的图(节点V={n1, n2, n3, n4},距离d(n1, n2) = 10;D (n1,n3) = 3;D (n3,n2) = 3(其他都是无穷大)
从n1开始你发现n2的代价是10
你以3的代价发现了n3
从n2你没有发现到n2 (n1-n3-n2)的更短的路径,因为你已经把n2标记为访问过。
我不确定,如果我是对的。- 使用 Dijkstra 算法跟踪两个节点之间的最短路径
- 我的Dijkstra算法没有选择短路径
- 运行Dijkstra算法的问题
- Dijkstra 最短路径算法性能 std::p riority_queue VS std::set.
- 具有恒定权重的 Dijkstra 最短路径算法
- 使用 Dijkstra 算法计算两个节点之间的最短路径
- Dijkstra算法找到两个顶点之间的最短距离 c++
- Dijkstra算法条件不正确
- 如何使用boost::graph dijkstra的算法,如果顶点属性是指针?
- C Dijkstra算法 - 打印边缘名称/类型
- Dijkstra算法:内存消耗
- dijkstra算法的C++程序中的分割错误
- 具有邻接列表的 Dijkstra 算法
- Dijkstra的算法openmp奇怪行为
- 我对 Dijkstra 算法的实现一直搞砸
- dijkstra算法带有邻接列表无方向的图
- 最短路径的dijkstra算法的时间复杂度是否取决于所使用的数据结构?
- 扩展 Dijkstra 算法实现
- 没有对角线移动的Dijkstra算法
- 将 Dijkstra 算法与柠檬图库结合使用