數據結構(最短路徑)

最短路徑算法

  在網圖和非網圖中,最短路徑的含義是不一樣的:數組

  • 網圖是兩頂點通過的邊上的權之和最小的路徑
  • 非網圖是兩頂點之間通過的邊數最少的路徑
  • 把路徑起始的第一個頂點稱爲源點。最後一個頂點稱爲終點

  主要的方法有兩種:spa

  • 迪傑斯特拉算法:求頂點到全部頂點的最短路徑。O(n²)
  • 弗洛伊德算法:求全部頂點到全部頂點的最短路徑。O(n³)

迪傑斯特拉算法3d

算法思路:code

  一步步求與每一個頂點的最短路徑,過程當中都是基於已經求出的最段路徑的基礎上,求得更遠頂點的最段路涇,最終獲得想要頂點的最段路徑(其實與普利姆算法是很是類似的)blog

方法:遞歸

  • 用3個數組:final數組,ShortPathTable數組,Patharc數組
  • final數組:標記頂點是否已求出最短路徑(0/1)
  • ShortPathTable數組:存儲當前進度源點到各頂點的最短距離
  • Patharc數組:存儲當前對應位置當前ShortPathTable數組距離路徑的前驅

 1 #define MAXVEX 9//宏定義圖的最大定點數
 2 #define INFINITY 65535//路不通時的默認值
 3 
 4 typedef int Patharc[MAXVEX]//用於存儲最段路經下標的數據
 5 typedef int ShortPathTable[MaxVEX]//用於存儲到各點的最短路徑的權值和
 6 
 7 //G:圖結構:are,矩陣二維數組;numVertexes,圖中頂點數
 8 //A:用於傳入源點
 9 //P就是Patharc數組,用於存儲源點到下標位置對應頂點爲終點的最短路徑的倒數第二個頂點的下標(最段路經終點的前驅)
10 //D就是ShortPathTable數組,用於存儲各源點A到其餘各點的最短路徑權之和
11 void ShortestPath_Dijkstar(MGraph G,int A,patharc *P,ShortPathTable *D){
12     int v,w,k,min;
13     int final[MAXVEX];//標記數組:用於標誌是否已經找到源點到對定位置的最段路經【0表示未找到,1表示已經找到】
14     
15     //初始化數據
16     for(v=0;v<G.numVertexes;v++){
17         final[v]=0;//所有頂點初始化爲未找到最段路涇
18         (*D)[v]=G.are[A][v];//由於尋找A下標頂點到各頂點的最短路徑,因此初始化時就是爲矩陣中第v行的數據(這行數據就是這個頂點到各頂點的權)
19         (*P)[v]=0;//初始化路徑數組爲0
20     }
21     (*D)[A]=0;//源點到源點的路徑權爲0
22     final[A]=1;//源點到源點的路徑已經找到
23 
24     //開始循環,找源點到其餘[G.numVertexes-1]個頂點的最短路徑
25     for(v=1;v<G.numVertexes;v++){//【循環1】:循環一次找到一個源點到其餘點【X】的最短路徑
26         min=INFINITY;
27         for(w=0;w<G.numVertexes;w++){
28             if(!final[w] && (*D)[w]<min){//在未找到最短路徑的頂點中找當前距離源點權最近的那個頂點,這個頂點就是【循環1】本次循環所找到的【X】
29                 k=w;//記錄此次找到最短路徑的終點下標
30                 min=(*D)[w];//記錄此次找到點的最短路徑的權(這裏的權就是這條路徑的權之和)
31             }
32         }
33         final[k]=1;//標記源點到該頂點爲終點的最短路徑已經找
34 
35         //修正當點進度源點到各點的最短距離;由於爲源點多加了一條邊,就爲源點到各點添加了若干條路,這些路會有刷新源點到其餘點的最短距離
36         for(w=0;w<G.numVertexes;w++){
37             //未找最短路徑到的頂點【Y】中;從源點到【X】再到【Y】的距離小於原先距離,就刷新了原先到【Y】的距離
38             if(!final[w] && (min+G.arc[k][w] < (*D)[w])){
39                 (*D)[w]=min+G.arc[k][w];//刷新該距離
40                 (*P)[w]=k;//記錄刷新到w頂點的最短距離的頂點,也是這條當前最短距離路徑的前驅
41             }
42         }
43     }
44 }

弗洛伊德算法class

  求是是全部頂點到全部頂點的距離;O(n³)test

算法思路:基礎

  判斷兩頂點之間依次通過任意中間點是否會減短原先路徑,能夠的話就在路徑上添加這個中間點,判斷過所有中間點後就獲得了全部能減短路徑的中間點,那麼兩點和這些有效的中間點之間的路徑就都成了短路徑;

查找最短路徑:

  查找時則是在Pathmatirx數組中查看是否存在中間點(-1表明沒有中間點);如有中間點則遞歸查找源點到中間點的最短距離中間點到終點的最短路徑,沒有中間點就表示源點直接到終點就是最短路徑,打印這條路徑,返回便可;

方法:

  • 定義中間點
  • 剛開始定義中間點位0,那麼就判斷所有頂點中任意兩頂點,源點經過0再走向終點的距離是夠小於源點直接走向終點的距離
  • 小於的話,那麼就在Pathmatirx數組中Pathmatirx【源點下標】【終點下標】位置修改成中間點下標的位置;不然不作處理
  • 循環①,③,③步驟,讓中間點從0~【G.numVertexes-1】循環過去便可

 1 #define MAXVEX 9//宏定義圖的最大定點數
 2 #define INFINITY 65535//路不通時的默認值
 3 
 4 typedef int Pathmatirx[MAXVEX][MAXVEX]//用於存儲最段路經下標的數據
 5 typedef int ShortPathTable[MaxVEX][MaxVEX]//用於存儲到各點的最短路徑的權值和
 6 
 7 void ShortesPath_Floyd(MGraph G,Pathmatirx *D,ShortPathTable *D){
 8     int v,w,k;
 9     //初始化D和P
10     for(v=0;V<G.numVertexes;v++){
11         for(w=0;w<G.numVertexes;w++){
12             (*D)[v][w]=G.matirx[v][w];
13             (*P)[v][w]=w;
14         }
15     }
16 
17     //弗洛伊德算法
18     for(k=0;k<G.numVertexes;k++){
19         for(v=0;v<G.numVertexes;v++){
20             for(w=0;w<G.numVertexes;w++){
21                 if( (*D)[v][w] > (*D)[v][w] + (*D)[k][w] ){
22                     (*D)[v][w]=(*D)[v][w]+(*D)[k][w];
23                     (*P)[v][w]=(*P)[v][k];
24                 }
25             }
26         }
27     }
28 }
29 
30 void printPath(MGraph G,int u,int v,int Pathmatirx[][MAXVEX]){
31     int mid;
32     if(Pathmatirx[u][v]==-1)
33         printf("<%c,%c>  ",G.lin[u],G.lin[v]);
34     else{
35         mid= Pathmatirx[u][v];
36         printPath(G,u,mid,Pathmatirx);
37         printPath(G,mid,v,Pathmatirx);
38     }
39 }
相關文章
相關標籤/搜索