[英]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.