輕鬆掌握Dijkstra算法(最短路徑算法)


void ShortestPath_DIJ(MGraph G, int v0, PathMatrix &P, ShortPathTable &D)
{
    /**
     * 核心原理:
     * 記已求得的最短路徑終點的集合爲S,假設要加入的終點是x頂點,那麼下一條最短路徑要麼是
     * 直接弧(v0,x),要麼就是中間經過S中頂點而最後到達終點x的路徑(v0,...,x)。
     * 證明:(反證法)
     * 假設下一條最短路徑中經過一個頂點不在S中,那麼說明存在一條終點不在S而長度比此路徑短的路徑。
     * 但是這是不可能的,因爲算法是按路徑長度遞增的次序來產生各路徑的,故長度比此路徑短的所有路徑
     * 均已產生,它們的終點必定在S中,即假設不成立。(理解:如果有一條最短路徑中經過一個頂點不在
     * S中,由於這個不在S中的頂點到終點x的弧權值大於0,所以從起始點v0到這個頂點的最短路徑比起始
     * 點v0到終點x的最短路徑肯定要短,那麼這一次選取的終點就不應該是x了,與假設矛盾。)
     */
   
    /**
     * 定義說明:
     * 用Dijkstra算法求v0點到其它各個頂點的最短路徑問題。
     * G表示用二維表數組表示的圖信息,其中(v,w)表示頂點v到頂點w的邊權值。
     * v0表示圖G中的起始點。
     * D是一個記錄起始點v0到各個頂點的最短路徑長度的一維數組。
     * 若P[v][w]爲TRUE,則表示從v0頂點到v頂點的最短路徑經過w頂點。
     * 若final[v]爲TRUE,則表示v頂點已經被包含在最短路徑集合中。
     */
   
    /**
     * 處理過程:
     * 1. 初始化操作(最短路徑頂點集合S、最短路徑矩陣P、最短路徑數組D)
     * 2. 主循環操作
     *      2.1 根據最短路徑數組D來挑選一個頂點加入到已處理的集合S中(最短路徑頂點集合S)
     *      2.2 最新當前最短路徑數組D和最短路徑矩陣P(最短路徑矩陣P、最短路徑數組D)
     */
   
    int v = 0;
    int w = 0;
    int i = 0;
    int j = 0;
    int min = INF;                          /** INF表示無窮大 */
    int* final = new int[G.vexnum];         /** 表示最短路徑頂點集合S */

                                            /** 初始化操作(最短路徑頂點集合S、最短路徑矩陣P、最短路徑數組D) */
    for(v = 0; v < G.vexnum; v++)
    {
        final[v] = FALSE;                   /** 初始化最短路徑頂點集合S */
        D[v] = G.arcs[0][v];                /** 初始化最短路徑數組D */
        for(w = 0; w < G.vexnum; w++)
        {
            P[v][w] = FALSE;                /** 初始化最短路徑矩陣P */
        }
        if(D[v] < INF)
        {
                                            /** 第一次以起始點v0來記錄最短路徑矩陣P */
            P[v][v0] = TRUE;
            P[v][v] = TRUE;
        }
    }
    final[v0] = TRUE;                       /** 第一次以起始點v0加入到最短路徑頂點集合S */
    D[0] = 0;                               /** 第一次以起始點v0記錄初始化最短路徑數組D */
   
                                            /** 主循環操作 */
    for(i = 1; i < G.vexnum; i++)
    {
                                            /** 根據最短路徑數組D來挑選一個頂點加入到已處理的集合S中 */
        min = INF;
        for(w = 0; w < G.vexnum; w++)
        {
            if(!final[w] && min > D[w])
            {
                min = D[w];
                v = w;
            }
        }
        final[v] = TRUE;                    /** 更新最短路徑頂點集合S(將新頂點加入集合S中) */
        for(w = 0; w < G.vexnum; w++)
        {
            if(!final[w] && min + G.arcs[v][w] < D[w])
            {
                D[w] = min + G.arcs[v][w];  /** 更新最短路徑數組D(保持D數組是最小的路徑值) */
                                            /** 更新最短路徑矩陣P(記錄到P[w][w]最短路徑經過自身,且照搬前面頂點v的路徑過程) */
                P[w][w] = TRUE;
                for(j = 0; j < G.vexnum; j++)
                {
                    P[w][j] = P[v][j];
                }
            }
        }
    }
}

發佈了31 篇原創文章 · 獲贊 26 · 訪問量 32萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章