Dijkstra最短路徑算法

前言

Dijkstra算法是應用于圖中單源最短路徑的搜索。我在這記錄下我在學習該算法時的一些想法、理解與總結。首先我會寫一段預備知識,以便于之后的理解。

算法基礎

  1. 選擇點到其他點的最短距離
  2. 局部最優是全局最優的充分必要條件

基礎1:
在一張權值都是 同號 的圖中,假設存在:①點A;②與A點相連的最短弧的弧頭C;那么路徑(A,C)為點A到點C的最短路徑。

圖1

如圖所示,(A,C) 是點A到點C的最短路徑。
解釋:在權值都為正的情況下,沒走一個點,其路徑只會增加。所以與點A相接最短的弧是抵達弧頭的最短路徑。

正文

集合{S}:用來存放已尋找到最短路徑的點。
集合{V}:全集
集合{V - S} 剩下的未找到最短路徑的點集
如果集合{S}包括了所有的點,那么圖的單源最短路徑尋找結束。
算法開始的時候集合{S}中只包括原點,Dijkstra算法的過程是逐漸填充集合{S}的過程。

怎么填充?

在集合{V - S}中找一個距離{S}最近的點,命其為 點V 將其加入集合{S}中。

解釋如圖:

圖2

注意:
①這張圖和前面那張圖沒有任何聯系;
②圖中的虛線并不是真實存在的線,虛線上的數組不是點至原點的路徑長度,而是集合{S}到點的路徑長度,這些數值的需要計算;

在填充的過程中,會發現一個問題。每添加一個點之后,集合{S} 至集合{V - S}中點的最短距離可能會發生變化。
例如 圖2 :添加點C之后,集合{S}到點B的最短距離變為先經過點C,在到達點B。即 5+4 < 10。因此再每加入一個點后就要時刻更新集合{S} 至 集合{V - S}中點的最短距離。

總結:Dijkstra算法一共需要三步

  • ① 創建集合{S},將原點加入集合{S}。計算集合{S}到各點的距離,并儲存。
  • ② 尋找目前距離集合{S}最短距離的 點V ,將 點V 加入集合{S}
  • ③ 更新集合{V - S} 中的點距離 集合{S} 的距離

應用

#define MAX_SIZE 100
int route[MAX_SIZE][MAX_SIZE];//路徑
int curDis[MAX_SIZE];//當前最短路徑
int pre[MAX_SIZE];//前驅
bool Set[MAX_SIZE];//集合{S}
int N;//結點個數
void shortestPath(const int start, const int dest)
    {
        //初始化
        fill(Set, Set+N, false);
        fill(curDis, curDis+N, INF);
        int i;
        for(i = 0 ; i < N ; i++) pre[i] = i;
        curDis[start] = 0;
        //遍歷除原點外的頂點,因為每次循環都會尋找到一個可以加入集合{S}中的點,
        for(i = 0 ; i < N ; i++){
            //尋找 {V-S} 到原點最短路徑的點
            int v = -1, MIN = INF;
            for(int j = 0 ; j < N ; j++){
                if(!Set[j] && curDis[j] < MIN)
                    v = j;
                    min = curDis[j];
                }
            }
            if(v == -1) break;//有些結點無法到達
            Set[v] = true;
            //更新 {V-S} 中的最短路徑
            for(int j = 0 ; j < N ; j++){
                if(!Set[j] && route[u][j] != INF){
                  if(curDis[v] + route[v][j] < curDis[j]){
                      curDis[j] = curDis[v] + route[v][j];
                      pre[j] = u;//設置前驅
                  }else if(distance == shortestDistance[iY]){
                      //這里處理第二選擇情況
                  }
              }
            }
        }
    }

注意:權值必須是全是正的,或者全是負的。兩種情況的結果會不同,我只做在權值全為正的情況。如果想求最大路徑,可以將正權值都制負,然后使用Dijkstra算法尋找最小值。然后再去絕對值,則是最大路徑。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容