【问题标题】:Dijkstra's algorithm in C++C++ 中的 Dijkstra 算法
【发布时间】:2015-05-27 06:51:29
【问题描述】:

我需要通过 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 Source\n");
   for (int i = 0; i < N; i++)
      printf("%d \t\t %d\n", 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;
}

【问题讨论】:

  • 最近的[v] ←????(????????) = 最近的[v] ←w(uv)
  • 不是问题,但通常你会把for (int i = 0; i &lt; N; i++) dist[i] = INT_MAX, sptSet[i] = false;写成for (int i = 0; i &lt; N; i++) {dist[i] = INT_MAX; sptSet[i] = false;};逗号运算符通常不仅仅用于将多个语句放在一行中。
  • @SJuan76 谢谢,我已经进行了相应的编辑。问题是,这段代码与它看起来的伪代码不匹配。我想知道它不匹配的部分。
  • 目前,代码无法编译。 sptSet[i] = false; 在 for 循环之外(这就是为什么我告诉大家总是放 {},即使里面有单行语句。
  • 问题一:需要实现nearestparent吗?问题2:是否需要使用优先级队列(最小堆)?

标签: c++ c dijkstra


【解决方案1】:

最明显的不匹配是您的代码没有与伪代码的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];

条件&amp;&amp; dist[u] != INT_MAX 与伪代码中的任何内容都不对应。 (这也是不必要的,因为u 是由minDistance() 返回的,因此应该始终满足该条件。

可以想象,您的教师也可能对您打印最小路径长度而不是返回它们感到不满。这在一定程度上取决于伪代码方言,但我倾向于将Dist 在参数列表中的出现视为它是一个输出参数,而不仅仅是一个内部变量。

如果你的导师非常挑剔,那么也许你可以通过指出伪代码中的一些明显错误来放松一下:

  • 如前所述,Nearest 不是参数,它被写入但从不读取。
  • 看起来条件 if Dist[u] ← w(uv) &lt; Dist[v] then 应该改为 if Dist[u] + w(uv) &lt; Dist[v] then。 (您已经实现了正确的版本,这可以解释为与伪代码的另一个区别。)
  • 看起来Parent[r] ← u 应该是Parent[v] ← u

当然,你的导师可能希望你准确地实现伪代码,错误和所有......

作为一种策略,我会尝试使用与伪代码更好匹配的变量名。我认为你的导师基于这些理由拒绝代码是不公平的,但是如果你能更接近你的名字。

当我在谈论您的代码时,顺便说一下,我观察到虽然您的 minDistance() 函数似乎实现了伪代码的要求,但它以一种低效的方式实现了这一点(而且 Dijkstra 一开始并不是特别有效)。通常的方法使用最小堆来跟踪已经看到但尚未访问的节点,这将选择最小距离节点的成本从 O(n) 降低到 O(log n)。当然,这对您测试的元素如此之少并不重要,但对于大图来说,差异是巨大的。

【讨论】:

  • 非常感谢您指出错误,我的讲师同意以下错误:- - 看起来像条件​​ if Dist[u] ← w(uv)
【解决方案2】:

问题是我相信您的 minDistance 函数,您似乎只更新未访问的节点(第 10 行 if (sptSet[v] == false && dist[n]

从 n1 开始,您会发现 n2,成本为 10

你还发现了 n3,成本为 3

从 n2 您没有发现到 n2 (n1-n3-n2) 的较短路径,因为您已将 n2 标记为已访问。

我不确定,如果我是赖特的话。如果不是不要怪我。

【讨论】:

  • 不,它匹配 minDistance() 仅考虑未访问节点的伪代码(通常是 Dijkstra)。在伪代码中,这对应于条件“在所有 u 上,使得 InTheTree[u] = .false。”。 Dijkstra 实现通常使用最小堆来管理此选择,这样更有效,但伪代码不需要这样做。
猜你喜欢
  • 2014-12-22
  • 2012-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多