1. 程式人生 > >資料結構圖之三-----------最短路徑

資料結構圖之三-----------最短路徑

最短路徑?別亂想哈,其實就是字面意思,一個帶邊值的圖中從某一個頂點到另外一個頂點的最短路徑。

官方定義:對於內網圖而言,最短路徑是指兩頂點之間經過的邊上權值之和最小的路徑。

並且我們稱路徑上的第一個頂點為源點,最後一個頂點為終點。

由於非內網圖沒有邊上的權值,所謂的最短路徑其實是指兩頂點之間經過的邊數最少的路徑。

別廢話了!整點實際的哈,你能很快計算出下圖中由源點V0到終點V8的最短路徑嗎?

【2】迪傑斯特拉演算法

迪傑斯特拉演算法是按路徑長度遞增的次序產生最短路徑的思路求解。

具體演算法及其詳細講解如下:

閱讀程式前,先要搞明白幾個陣列作用:

final[w]=1; 表示V0到Vw頂點已經有最短路徑的結果

ShortPathTable[w]; 表示V0到Vw頂點的最短路徑權值和

Pathmatirx[w]; 表示V0到Vw頂點的前驅頂點下標值

開始呼叫演算法前,我們需要為案例圖建立鄰接矩陣圖,如下所示:

(1)程式開始執行,final陣列是為了標記V0到某頂點是否已經求得最短路徑。

  如果V0到Vw已經有結果,那麼final[w]=1;

(2)第5~10行,是對資料初始化工作。 此時final陣列均賦值為0,表示所有點均未求得最短路徑。

  D陣列為 {0,1,5,65515,65535,65535,65535,65535,65535}。因為V0與V1和V2的邊權值為1和5。

  P陣列全為0,表示目前沒有路徑。

(3)第11行,表示V0至V0路徑為0。

  第12行,表示V0點到V0點已經求得最短路徑,因此final[0]=1。

  此時final陣列為 {1,0,0,0,0,0,0,0,0},此時整個初始化工作完成。

(4)第13~33行為主迴圈,每次迴圈求得V0與一個頂點的最短路徑。除去V0,因此索引從1開始。

(5)第15~23行,先令min為65535的極大值,通過w控制迴圈,與D[w]比較找到最小值為min=1,同時確定k=1。

(6)第24行,由k=1可知與V0最近的頂點是V1,並且由D[1]=1知道此時V0到V1的最短路徑是1。

  因此再將對應的final[1]設定為1。此時final陣列為 {1,1,0,0,0,0,0,0,0}

(7)第25~32行是一迴圈,此迴圈甚為關鍵。

  它的目的是在剛才已經找到V0與V1的最短路徑基礎之上,對V1與其它頂點的邊進行計算,得到V0與它們的當前最短距離,如圖所示:

  因為min=1,所以D[2]=5不再是V0到V2的最短路徑,現在D[2]=V0->V1->V2=min+3=4, D[3]=V0->V1->V3=min+7=8,

  D[4]=V0->V1->V4=min+5=6,於是D陣列當前值為 {0,1,4,8,6,65535,65535,65535,65535}。

  而P[2]=1,P[3]=1,P[4]=1,其表示V0到V2,V3,V4點的最短路徑它們的前驅均是V1。

  此時P陣列為 {0,0,1,1,1,0,0,0,0}。

(8)新一輪迴圈,此時i=2。第15~23行,對w迴圈,注意因為final[0]=1和final[1]=1,由第18行的!final[w]可知:

  V0與V1並不參與最小值的獲取。通過迴圈比較,找到最小值min=4,k=2。

(9)第24行,由k=2,表示已經求出V0到V2的最短路徑,並且由D[2]=4知道最短路徑距離為4。

  因此將V2對應的final[2]設定為1,此時final陣列為 {1,1,1,0,0,0,0,0,0}。

(10)第25~32行,在剛才已經找到V0與V2的最短路徑的基礎上,對V2與其它頂點的邊進行計算,得到V0與它們的最短距離。

  如圖所示:

  因為min=4,所以D[4]=6不再是V0到V4的最短距離,現在D[4]=V0->V2->V4=min+1=5,D[5]=V0->V2->V5=min+7=11。

  因此D陣列當前值為 {0,1,4,8,5,11,65535,65535,65535,65535}。

  而原本P[4]=1,此時P[4]=2,P[5]=2,它表示的意思是V0到V4和V5的最短路徑前驅均為V2。

  此時P陣列為 {0,0,1,1,2,2,0,0,0}。

(11)重新再開始一輪迴圈,此時i=3。第15~23行,通過對w迴圈比較找到最小值min=5,k=4。

(12)第24行,由k=4表示已經求出V0到V4的最短路徑,並且由D[4]=5知道最短路徑距離為5。

  因此將V4對應的final[4]設定為1。此時final陣列為 {1,1,1,0,1,0,0,0,0}。

(13)第25~32行,對V4與其它頂點的邊值進行計算,得到V0與它們的當前最短距離,如圖所示:

  因為min=5,所以D[3]=8不再是V0到V3的最短路徑,現在D[3]=V0->V4->V3=min+2=7,同理:

  D[5]=V0->V4->V5=min+3=8,D[6]=V0->V4->V6=min+6=11,

  D[7]=V0->V4->V7=min+9=14,因此,D陣列當前值為 {0,1,4,7,5,8,11,14,65535}。

  而原本P[3]=1,此時P[3]=4,原本P[5]=2,此時P[5]=4。

  另外P[6],P[7]=4,它表示V0到V3,V5,V6,V7點的最短路徑它們的前驅是V4。

  此時P陣列值為 {0,0,1,4,2,4,4,4,0}。

(14)之後的迴圈完全類似。得到最終的結果,如圖所示:

  此時final陣列為 {1,1,1,1,1,1,1,1,1},它表示所有的頂點均完成了最短路徑的查詢工作。

  此時D陣列為 {0,1,4,7,5,8,10,12,16},它表示V0到各個頂點的最短路徑數,比如D[8]=1+3+1+2+3+2+4=16。

  此時的P陣列為 {0,0,1,4,2,4,3,6,7}:

  這個P陣列值可能難理解一些。比如P[8]=7,它表示要檢視V0到V8的最短路徑時,頂點V8的前驅是V7;

  再由P[7]=6表示要檢視V0到V7的最短路徑時,頂點V7的前驅是V6,同理,P[6]=3表示V6的前驅是V3。

  這樣就可以得到:V0到V8最短路徑為V8<-V7<-V6<-V3<-V4<-V2<-V1<-V0

  即就是: V0->V1->V2->V4->V3->V6->V7->V8。