最短路徑問題是圖研究中的一個經(jīng)典算法問題, 旨在尋找圖(由結(jié)點和路徑組成的)中兩結(jié)點之間的最短路徑。 算法具體的形式包括:
確定起點的最短路徑問題 - 即已知起始結(jié)點,求最短路徑的問題。
確定終點的最短路徑問題 - 與確定起點的問題相反,該問題是已知終結(jié)結(jié)點,求最短路徑的問題。在無向圖中該問題與確定起點的問題完全等同,在有向圖中該問題等同于把所有路徑方向反轉(zhuǎn)的確定起點的問題。
確定起點終點的最短路徑問題 - 即已知起點和終點,求兩結(jié)點之間的最短路徑。
全局最短路徑問題 - 求圖中所有的最短路徑。
Dijkstra(迪杰斯特拉)算法
Dijkstra算法是典型的最短路徑路由算法,用于計算一個節(jié)點到其他所有節(jié)點的最短路徑。主要特點是從起始點開始,采用貪心算法的策略,每次遍歷到始點距離最近且未訪問過的頂點的鄰接節(jié)點,直到擴展到終點為止。
思路:
- 初始化一個
Final
數(shù)組,全部設置為0,用于表示節(jié)點V0
到某個頂點Vw
,是否已經(jīng)求得了最短路徑的標記,如果已有則標記為1; - 聲明一個
D
數(shù)組,表示節(jié)點V0 到某個頂點Vw 的路徑; - 聲明一個
P
數(shù)組,表示當前結(jié)點Vw 的前驅(qū)頂點的下標; - 初始化
Final
、D
,P
數(shù)組; - 初始化
min
為無窮大,遍歷 D 數(shù)組 找到對應最小權值min
的頂點,記錄對應下標k,標記Final[k] = 1
,表明找到最短路徑; - 之后通過Vk頂點向外擴散找到有關聯(lián)邊的頂點Vw更新
D
數(shù)組,若!final[w] && min + G.arc[k][w] < D[w]
,則取min + G.arc[k][w]
更新D[w]
,更新P[w] = k
; - 遍歷V1到 Vw ,重復上兩條操作直到final數(shù)組全部為1,求得V0到其他頂點的最短路徑。
代碼實現(xiàn):
/*
G;網(wǎng)圖
v0: v0開始的頂點
p[v]:前驅(qū)頂點下標
D[v]:表示從v0到vw的最短路徑長度和
*/
void ShortestPath_Dijkstra(MGraph G, int v0, Patharc *P, ShortPathTable *D)
{
int v,w,k,min;
k = 0;
int final[MAXVEX];
final[0] = 1;
for(v = 0; v < G.numVertexes;v++){
final[v] = 0;
(*D)[v] = G.arc[0][v];
(*P)[v] = 0;
}
(*D)[v0] = 0;
final[v0] = 1;
(*P)[v0] = -1;
for (v = 1; v < G.numVertexes; v++)
{
min = INFINITYC;
for (w = 0; w < G.numVertexes; w++)
{
if (final[w] != 1 && (*D)[w] < min)
{
//下標
k = w;
//最小權值
min = (*D)[w];
}
}
final[k] = 1;
for (w = 0; w < G.numVertexes; w++)
{
if (final[w] != 1 && min + G.arc[k][w] < ( *D)[w])
{
(*D)[w] = min + G.arc[k][w];
(*P)[w] = k;
}
}
}
}
Floyd算法
Floyd算法又稱為插點法,是一種利用動態(tài)規(guī)劃的思想尋找給定的加權圖中多源點之間最短路徑的算法。通過一個圖的權值矩陣求出它的每兩點間的最短路徑矩陣。
算法思路
從任意一條單邊路徑開始。所有兩點之間的距離是邊的權,如果兩點之間沒有邊相連,則權為無窮大。
對于每一對頂點 u 和 v,看看是否存在一個頂點 w 使得從 u 到 w 再到 v 比已知的路徑更短。如果是更新它。
1 把圖用鄰接矩陣D表示出來,定義一個矩陣P用來記錄所插入點的信息;*
2 初始化P,P[v][w]表示從Vv到Vw需要經(jīng)過的點,P[v][w]=w
;
3 對于每一對頂點 v 和 w,看看是否存在一個頂點 k 使得從 v 到 k 再到 w 比已知的路徑更短。如果是更新D[v,w]
,各個頂點插入圖中,比較插點后的距離與原來的距離,D[v][w] = min( D[v][w], D[v][k]+D[k][w] )
,如果D[v][w]
的值變小,則P[v][w]=k
。*
4 在D中包含有兩點之間最短道路的信息,而在P中則包含了最短通路徑的信息
代碼實現(xiàn):
void ShortestPath_Floyd(MGraph G, Patharc *P, ShortPathTable *D) {
int v, w, k;
for (v = 0; v < G.numVertexes; v++) {
for (w = 0; w < G.numVertexes; w++) {
(*D)[v][w] = G.arc[v][w];
(*P)[v][w] = w;
}
}
for (k = 0; k < G.numVertexes; k++) {
for (v = 0; v < G.numVertexes; v++) {
for (w = 0; w < G.numVertexes; w++) {
if ((*D)[v][w] > (*D)[v][k] + (*D)[k][w]) {
(*D)[v][w] = (*D)[v][k] + (*D)[k][w];
(*P)[v][w] = (*P)[v][k];
}
}
}
}
}