簡體   English   中英

Dijkstra在C ++中的算法

[英]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 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;
}

最明顯的不匹配是您的代碼沒有與偽代碼的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的外觀作為輸出參數的指示,而不僅僅是內部變量。

如果你的教練非常挑剔,那么也許你可以通過指出偽代碼中的一些明顯錯誤來獲得一些松懈:

  • 如前所述, Nearest不是一個參數,它是寫入但從未讀取的。
  • if Dist[u] ← w(uv) < Dist[v] then看起來像是if Dist[u] + w(uv) < Dist[v] then條件似乎是條件。 (您已經實現了正確的版本,這可以解釋為與偽代碼的另一個區別。)
  • 它看起來像Parent[r] ← u應該是Parent[v] ← u

當然,可能是你的教練要求你准確地實現偽代碼,錯誤和所有....

作為一個策略問題,我會嘗試使用更好地匹配偽代碼的變量名稱。 我不認為你的導師在這些理由上拒絕代碼是不公平的,但是如果你跟你的名字更加接近,那么將C ++代碼與偽代碼進行比較對每個人來說都會更容易。

雖然我正在討論你的代碼,順便說一下,我觀察到雖然你的minDistance()函數似乎實現了偽代碼的要求,但它以低效的方式實現(並且Dijkstra開始時並不是特別有效)。 通常的方法是使用最小堆來跟蹤已經看到但尚未訪問的節點,從而降低了從O(n)到O(log n)選擇最小距離節點的成本。 當然,並不是因為您正在測試的元素如此之少,但對於大型圖形而言,差異是巨大的。

問題是我相信你的minDistance函數,似乎你只更新未訪問的節點(第10行if(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

你發現n3的成本是3

從n2你不會發現到n2(n1-n3-n2)的較短路徑,因為你已經將n2標記為已訪問過。

我不確定,如果我是懷疑的話。 如果不是不怪我。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM