從某個源點到其余各頂點的最短路徑
迪傑斯特拉(Dijkstra)算法
迪傑斯特拉算法是一個按路徑長度遞增的次序產生最短路徑的算法。(負值圈該算法無效)
算法描述:
- 假設用帶權的鄰接矩陣 arcs表示帶權有向圖,arcs[i][j]表示弧<vi,vj>上的權值;若<vi,vj>不存在,則arcs[i][j]為∞,S為已找到的從v0頂點出發的最短路徑的終點的集合,初始狀態為空.
- 選擇 v0到 V-S中頂點構成的最短路徑<v0,vj>,並將vj加入S。
- 由於vj加入到S中,最短路徑發生變化,修改v0到V-S可能的最短路徑
- 重復第2、3步n-1次,得到從v0到圖上其余頂點的最短路徑是依次遞增的序列
該算法最終的得到的是一個遞增的最短路徑序列,每次循環中是先找到剩余路徑中的最短的一條,再更新一下剩余的最短路徑,好像一個選擇排序一樣,每次選擇后面的最小的一個放到前面,最終的到一個有序序列,該序列就是從源點到圖中各個頂點的最短路徑。
/* G.arcs : 帶權鄰接矩陣 vo : 源點 P : 存儲路徑的矩陣 D : 存儲 v0到 vi的最短路徑長度 */ void shortestPath_DLJ(MGraph G, int v0, PathMatrix &P, ShortPathTable &D) { /* 求從 v0頂點到其余頂點 v的最短路徑P[v]及帶權長度D[v] P[v][w]為true表示 w是從 v0到 v當前求得最短路徑上的頂點 final[v]為true表示已經求得從 v0到 v的最短路徑 , 即將頂點 v加入到 S集中 */ //初始化 for(v = 0; v < G.vexnum; v++){ final[v] = false; //若 v0到 v有弧,則賦給D[v]的為其權值,否則為INFINITY //G.arcs中兩頂點無弧,其值已為INFINITY D[v] = G.arcs[v0][v]; //置空路徑 for(w = 0; w < G.vexnum; w++) P[v][w] = flase; //若D[v]值小於INFINTY,說明 v0到 v有弧,v0, v自然在路徑上 if(D[v] < INFINTY){ P[v][v0] = true; P[v][v] = true;} } // 初始化,v0屬於 S集 D[v0] = 0; final[v0] = true; //開始主循環,每次求得 v0到 v頂點的最短路徑,將 v加入到 S集 //其余 G.vexnum - 1個頂點 for(i = 1; i < G.vexnum; i++){ //當前離 v0最短距離 min = INFINTY; for(w = 0; w < G.vexnum; w++) //頂點在 V-S中 if(!final[v]){ v = w; min = D[w];} //找到了,將 v加入到 S集 final[v] = true; /* 更新最短路徑及距離 因 v加入到 S集,產生了有 v頂點的新路徑 重新判斷最短路徑,用於下次找最短路徑 */ for(w = 0; w < G.vexnum; w++) if(!final[w] && min + G.arcs[v][w] < D[w]){ D[w] = min + G.arcs[v][w]; //將 v0到 v的路徑 P[v]賦給 P[w] //w也在該路徑上 P[w] = P[v]; P[w][w] = true; } } }
待續。。。
