當前位置:編程學習大全網 - 編程語言 - 誰能舉壹個Pascal中Dijkstra算法求單源最短路徑問題的例子並作壹些說明

誰能舉壹個Pascal中Dijkstra算法求單源最短路徑問題的例子並作壹些說明

[問題分析]

對於壹個含有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;

  • 上一篇:現在的畢業生應該踏踏實實幹壹個工作攢經驗好還是多次跳槽漲工資好?
  • 下一篇:vision畫圖軟件安裝-海信vision2.0如何安裝軟件
  • copyright 2024編程學習大全網