迪傑斯特拉算法

Dijkstra(迪傑斯特拉)算法是典型的最短路徑路由算法,用於計算一個節點到其他所有節點的最短路徑。主要特點是以起始點爲中心向外層層擴展,直到擴展到終點爲止(BFS、prime算法都有類似思想)。Dijkstra算法能得出最短路徑的最優解,但由於它遍歷計算的節點很多,所以效率低。

1、算法思想

令G = (V,E)爲一個帶權有向網,把圖中的頂點集合V分成兩組:已求出最短路徑的頂點集合S(初始時S中只有源節點,以後每求得一條最短路徑,就將它對應的頂點加入到集合S中,直到全部頂點都加入到S中);未確定最短路徑的頂點集合V-S。在加入過程中,總保持從源節點v到S中各頂點的最短路徑長度不大於從源節點v到V-S中任何頂點的最短路徑長度。
2、算法描述

(1)S爲已經找到的從v出發的最短路徑的終點集合,它的初始狀態爲空集,那麼從v出發到圖中其餘各頂點(終點)vi(vi∈V-S)可能達到的最短路徑長度的初值爲:

     d[i] = arcs[LocateVex(G, v)][i],vi∈V

(2)選擇vj,使得 d[j] = Min{d[i]|vi屬於V-S},vj就是當前求得的一條從v出發的最短路徑的終點。令S=S∪{j};

(3)修改從v出發到集合V-S上任一頂點vk可達的最短路徑長度。如果 d[j] + arcs[j][k] < d[k], 則修改d[k]爲:d[k] = d[j] + arcs[j][k];

(4)重複(2),知道所有頂點都包含在S中,此時得到v到圖上其餘各頂點的最短路徑是依路徑長度遞增的序列。

具體圖例與算法執行步驟:(從A開始,到各節點的最短路徑)

具體執行步驟如下圖所示:

PS:圖片右下角是原作者的博客地址。
3、算法具體實現

[cpp] view plain copy
typedef int PathMatrix; //用於存儲最短路徑序列的頂點下標數組
typedef EdgeType ShortPathTable; //用於存儲到各點最短路徑的權值和
[cpp] view plain copy
/* Dijkstra算法求有向網g的下標爲v0的頂點到其餘頂點下標爲v的最短路徑P[v]及帶權長度D[v] */
/* P[v]的值爲前驅頂點下標,D[v]表示v0到v的最短路徑長度和 */
void ShortestPath_DIJ(Graph *g, int v0, PathMatrix p[], ShortPathTable d[])
{
int i, v, w, k;
EdgeType min;
bool final[MAX_VEX]; /* final[w]=1表示求得頂點V0至Vw的最短路徑 */

//初始化數據  
for (v = 0; v < g->vexNum; v++)  
{  
    final[v] = false;      //全部頂點初始化爲未知最短路徑狀態  
    d[v] = g->arc[v0][v];  //將與v0點有連線的頂點加上權值  
    p[v] = v0;             //初始化路徑數組P爲v0  
}  
d[v0] = 0;                //v0至v0的路徑爲0  
final[v0] = true;         //v0∈S, v0至v0不需要求路徑  

//開始主循環,每次求得v0到某個v頂點的最短路徑,並 加入v到集合S  
for (i = 0; i < g->vexNum; i++)  
{  
    if (i == v0) continue;  
    min = INFINITY;  
    for (w = 0; w < g->vexNum; w++)    //尋找V-S中離v0最近的頂點  
    {  
        if (!final[w] && d[w] < min)  
        {  
            min = d[w];    //下標爲w的頂點離v0更近  
            v = w;  
        }  
    }  
            //if (v == t) break;    //如果只查找到下標爲t的某個頂點  
    final[v] = true;    //下標爲k的頂點併入集合S,即將當前找到了最短路徑的頂點標記爲true  

    //更新當前最短路徑及距離  
    for (w = 0; w < g->vexNum; w++)  
    {  
        //如果經過v頂點的路徑比現在這條路徑的長度短的話  
        if (!final[w] && (min + g->arc[v][w] < d[w]))  
        {  
            //說明找到了更短的路徑,修改D[w]和P[w]  
            d[w] = min + g->arc[v][w];  
            p[w] = v;  
        }  
    }  
}  

}
下面是根據路徑數組PathMatrix得到具體的路徑序列:

[cpp] view plain copy
// 查找從源點v到終點u的路徑,並輸出
void SearchPath(VertexType vex[], PathMatrix *prev,int v, int u)
{
int que[MAX_VEX];
int tot = 0;
que[tot++] = u; //終點u
int tmp = prev[u]; //到頂點下標u的路徑上的上一個頂點下標
while(tmp != v)
{
que[tot++] = tmp;
tmp = prev[tmp]; //到頂點下標tmp的路徑上的上一個頂點下標
}
que[tot] = v;
for(int i = tot; i >= 0; –i)
if(i != 0)
printf(“%c -> “, vex[que[i]]);
else
printf(“%c”, vex[que[i]]);
}
以上面的無向網爲例,運行結果截圖:

dijkstra算法兩個應用題:
HDOJ 1874 暢通工程續,現有解法:www.wutianqi.com/?p=1894
HDOJ 2544 最短路,現有解法:www.wutianqi.com/?p=1892

參考:http://hi.baidu.com/zealot886/item/c8a499ee5795bcddeb34c950

       數據結構(C語言版)

      http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html

推薦幾篇搜索算法相關的非常好的博文:

一、A*搜索算法

一(續)、A*,Dijkstra,BFS算法性能比較及A*算法的應用

二、Dijkstra 算法初探 (Dijkstra算法系列4篇文章)

二(續)、徹底理解Dijkstra算法

二(再續)、Dijkstra 算法+fibonacci堆的逐步c實現

二(三續)、Dijkstra 算法+Heap堆的完整c實現源碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章