1. 程式人生 > >圖之最短路徑

圖之最短路徑

    目前求最短路徑的演算法很多,下面2種是基本不再使用,但卻是經典的路徑演算法。其他路徑演算法有啟發式演算法A*,D*,還有樹形的RRT, RRT*等。

1. Dijkstra演算法

    a. 基本思想:求帶權有向圖中某個源點到其他各頂點的最短路徑,Dijkstra演算法十分適用。有向圖有N={V, arcs[i][j]}, 而生成單源最短路徑為Nt={Vt,dist[i]}。path[]表示從源點到頂點i之間的最短路徑前趨點(就是追溯點)。
    b. 實現過程:
      虛擬碼

void Dijkstra(Graph G,point v){
    //帶權有向圖,源點v
Vt=v; dist[i]初始值為arcs[0][i]。 i=123,..... ,n-1while(Vt!=V){ 選Vj,滿足<Vi, Vj>邊最小。dist[j] = MIN(dist[i]); Vt=Vt U Vj; dist[j] = cost; } }

      示意圖
這裡寫圖片描述
    c. 效能分析:使用鄰接矩陣表示時,時間複雜度O(|V|^2)。若使用帶權的鄰接表表示,dist修改會相應邊少,但時間複雜度仍然是O(|V|^2)。

2. Floyd演算法(基於矩陣最短路徑求解)

    a. 基本思想:對於一個所有權值都大於0的帶權有向圖,對每一對頂點Vi!=Vj,要求求出Vi與Vj之間的最短路徑和最短路徑長度。遞推產生一個n階方陣序列A(-1), A(0), A(1), ….., A(n-1)。其中A(k)[i][j]表示從頂點Vi到頂點Vj的路經長度,k表示第k個頂點的運算步驟。
    b. 實現過程:
       描述:初始時對於任意2個頂點vi和vj,若有邊則以此邊上的權值作為最短路徑長度,否則使用∞作為最短路徑長度。再向其中逐步在原路徑中引入頂點k(k=0,1,2,…..,n-1)作為中間頂點。如果引入中間頂點後,得到的路徑比原來的路徑長度減少了,則以此新路徑代替原路徑。

A(1)[i][j]=arcs[i][j]
A(k)[i][j]=MinA(k1)[i][j],A(k1)[i][k]+A(k1)[k][j]
其中使用迭代方式,沒迭代一次,在從Vi到Vj的最短路徑上就多考慮一個頂點,經過n次迭代之後所得到的A(n-1)[i][j]就儲存了vi到vj的最短路徑長度。
       示意圖
這裡寫圖片描述
    c. 效能分析:時間複雜度為O(|V|^3)。注:允許圖中有帶負權值的邊,但不允許由包含帶負權值的迴路。