對於壹個含有n個頂點和e條邊的圖來說,從某壹個頂點Vi到其余任壹頂點Vj的最短路徑,可能是它們之間的邊(Vi,Vj),也可能是經過k個中間頂點和k+1條邊所形成的路徑(1≤k≤n-2)。下面給出解決這個問題的Dijkstra算法思想。
設圖G用鄰接矩陣的方式存儲在GA中,GA[i,j]=maxint表示Vi,Vj是不關聯的,否則為權值(大於0的實數)。設集合S用來保存已求得最短路徑的終點序號,初始時S=[Vi]表示只有源點,以後每求出壹個終點Vj,就把它加入到集合中並作為新考慮的中間頂點。設數組dist[1..n]用來存儲當前求得的最短路徑,初始時Vi,Vj如果是關聯的,則dist[j]等於權值,否則等於maxint,以後隨著新考慮的中間頂點越來越多,dist[j]可能越來越小。再設壹個與dist對應的數組path[1..n]用來存放當前最短路徑的邊,初始時為Vi到Vj的邊,如果不存在邊則為空。
執行時,先從S以外的頂點(即待求出最短路徑的終點)所對應的dist數組元素中,找出其值最小的元素(假設為dist[m]),該元素值就是從源點Vi到終點Vm的最短路徑長度,對應的path[m]中的頂點或邊的序列即為最短路徑。接著把Vm並入集合S中,然後以Vm作為新考慮的中間頂點,對S以外的每個頂點Vj,比較dist[m]+GA[m,j]的dist[j]的大小,若前者小,表明加入了新的中間頂點後可以得到更好的方案,即可求得更短的路徑,則用它代替dist[j],同時把Vj或邊(Vm,Vj)並入到path[j]中。重復以上過程n-2次,即可在dist數組中得到從源點到其余各終點的最段路徑長度,對應的path數組中保存著相應的最段路徑。
下面給出具體的Dijkstra算法框架(註:為了實現上的方便,用壹個壹維數組s[1..n]代替集合S,用來保存已求得最短路徑的終點集合,即如果s[j]=0表示頂點Vj不在集合中,反之,s[j]=1表示頂點Vj已在集合中)。
Procedure Dijkstra(GA,dist,path,i);
{表示求Vi到圖G中其余頂點的最短路徑,GA為圖G的鄰接矩陣,dist和path為變量型參數,
其中path的基類型為集合}
Begin
For j:=1 To n Do Begin {初始化}
If j<>i Then s[j]:=0 Else s[j]:=1;
dist[j]:=GA[i,j];
If dist[j]<maxint Then path[j]:=[i]+[j] Else path[j]:=[ ];
End;
For k:=1 To n-2 Do
Begin
w:=maxint;m:=i;
For j:=1 To n Do {求出第k個終點Vm}
If (s[j]=0) and (dist[j]<w) Then Begin m:=j;w:=dist[j]; End;
If m<>i Then s[m]:=1 else exit;
{若條件成立,則把Vm加入到S中,
否則退出循環,因為剩余的終點,其最短路徑長度均為maxint,無需再計算下去}
For j:=1 To n Do {對s[j]=0的更優元素作必要修改}
If (s[j]=0) and (dist[m]+GA[m,j]<dist[j])
Then Begin Dist[j]:=dist[m]+GA[m,j];path[j]:=path[m]+[j];End;
End;
End;
(1)從壹個頂點到其余各頂點的最短路徑
對於壹個含有n個頂點和e條邊的圖來說,從某個頂點vi到其余任壹頂點vj的最短路徑,可能是它們之間的邊(vi,vj),也可能是經過k個中間點和k+1條邊所形成的路徑(1≤k ≤n-2)。
首先來分析Dijkstra的算法思想
設圖G用鄰接矩陣的方式存儲在GA中,GA[I,j]=maxint表示vi,vj是不關聯的,否則為權值(大於0的實數)。設集合S用來存儲保存已求得最短路徑的終點序號,初始時S=[vi]表示只有源點,以後每求出壹個終點vj,就把它加入到集合中並作為新考慮的中間頂點。設數組dist[1..n]用來存儲當前求得的最短路徑,初始時vi,vj如果是關聯的,則dist[j]等於權值,否則等於maxint,以後隨著新考慮的中間頂點越來越多,dist[j]可能越來越小。再設壹個與dist對應的數組path[1..n]用來存放當前最短路徑的邊,初始時vi到vj的邊,如果不存在邊則為空。
執行時,先從S以外的頂點(即待求出最短路徑的終點)所對應的dist數組元素中,找出其值最小的元素(假設為dist[m]),該元素值就是從源點vi到終點vm的最短路徑長度,對應的path[m]中的頂點或邊的序列即為最短路徑。接著把vm並入集合S中,然後以vm作為新考慮的中間頂點,對S以外的每個頂點vj,比較dist[m]+GA[i,j]與dist[j]的大小,若前者小,表明加入了新的中間頂點後可以得到更好的方案,即可求得更短的路徑,則用它代替dist[j],同時把vj或邊(vm,vj)並入到path[j]中。重復以上過程n-2次,即可在dist數組中得到從源點到其余個終點的最短路徑長度,對應的path數組中保存著相應的最短路徑。
為了實現上的方便,用壹個壹維數組s[1..n]代替集合s,用來保存已求得最短路徑的終點集合,即如果s[j]=0表示頂點vj不在集合中,反之,s[j]表示頂點vj已在集合中)。
Procedure dijkstra (GA,dist path,I)
begin
for j:= 1 to n do begin
if j<>I then s[j]:=0;{j不在集合中} else s[j]:=1;{j在集合中};
dist[j]:=GA[I,J];
IF dist [j]<maxint {maxint為假設的壹個足夠大的數}
Then path [j]:=[I]+[j]
Else path[j]:=[ ];
End;
For k:= 1 to n-1 do begin w:=maxint;m:=I;
For j:= 1 to n do{求出第k個終點Vm}
if (s[j]=0)and(dist[j]<w) then begin m:=j;w:=dist[j];end;
If m<>I then s[m]:=1 else exit;{若條件成立,則把Vm加入到s中,否則退出循環,因為
剩余的終點,其最短路徑長度均為maxint,無需再計算下去}
for j:=1 to n do {對s[j]=0的更優元素作必要修改}
if (s[j]=0)and (dist[m]+GA[m,j]<dist[j])
then begin
dist[j]:=dist[m]+GA[m,j];
path[j]:=path[m]+[j];
End;
End;
End;
用集合的思想:
for k:=1 to n-1 do
begin
wm:=max;j:=0;
for i:=1 to n do
if not(i in s)and(dist[i]<wm) then begin j:=i;wm:=dist[i];end;
s:=s+[j];
for i:=1 to n do
if not(i in s)and(dist[j]+cost[j,i]<dist[i]) then
begin dist[i]:=dist[j]+cost[j,i];path[i]:=path[j]+char(48+i);end;
end;