在解決單源點最短路徑的問題時,常常用到經典的dijkstra演算法,其演算法的本質思想是:按路徑長度遞增依次產生最短路徑。
下面給出演算法的大致流程:
1.初始化所有結點並將起始點設為標記,進入以下迴圈
2.在到達某點的最短路徑中找最小且未標記的點(可以用一維陣列表示)
如:陣列下標:0 1 2 3 4 5
len :- 0 5 10 2 -
這個陣列表示 1號節點為初始節點,1號節點到達2號節點的最短路徑為5,到3號為10,無法到達5號(具體可以以較大的數表示其路徑)。
從中找到乙個未標記且len最短的乙個,未標記用另一陣列記錄
如:陣列下標:0 1 2 3 4 5
標記 :0 1 0 0 1 0
此陣列表示從初始節點到達4號節點的最短路徑已找到
從以上兩個陣列中可以得出:此次迴圈找到的點為2號節點,進入下一步
3.標記找到的點,以此標記點為中間點重新計算所有未標記點的最短路徑(更新最短路徑表)
4.迴圈1.2步至n-1次(n為頂點數,若最後還有未被標記的,說明無法到達此點)
[cpp]view plain
copy
while
(count
} in[si]=1;
count++;
for(i=1;i<=n;i++)
//updata the length
}
}
核心部分是上面的兩個for迴圈,第乙個for迴圈遍歷所有結點,找到未標記並且長度最短的路徑;第二個for迴圈也是遍歷所有結點以上面找到的最短路徑結點為中間點更新最短路徑表;注意在第乙個for迴圈之後要標記找到的點(說明到達此點的最短路徑已找到)
下面用乙個例項來具體說明:
v0-v5 共6個節點,節點間路徑已標出,現要求從v0到其餘各節點的最短路徑;
有上面的演算法流程可知,在使用dijkstra演算法時需要幾個結構來儲存我們想要的資訊:
1.儲存這張圖的結構體
2.記錄v0到其餘各節點最短路徑的陣列(這裡設為len[n+1])
3.記錄某節點是否已找到最短路徑的陣列(這裡設為in[n+1])
接下來就是演算法實現部分:
1.標記v0 -- in[1]=1 初始化 len= 這裡陣列首元素未用到,陣列下標從1開始表示v0以此類推
2.第一次迴圈與v0相鄰的有v2、v4、v5,其中v2距離最短為10,標記v2,並且以v2為中間點(路徑為v0->v2->vx)更新最短路表,此時v3被更新為10+50=60,。
3.進入第二次迴圈,此時未被標記的有v1、v3、v4、v5,,其中從v0到這些的臨時最短路分別為infinite、60、30、100,從中找到最小的即v4,將v4標記為1,以v4為中間點(路徑為v0->v4->vx)更新最短路表,此時v3被更新為50,v5被更新為90。
4.進入第三次迴圈,此時未被標記的有v1、v3、v5,其中臨時最短路分別為infinite、50、90,從中找到最小的即v3,將v3標記為1,以v3為中間點(路徑為v0->v4->v3->vx)更新最短路表,此時v5被更新成60。
5.進入第四次迴圈,此時未被標記的有v1、v5,其中臨時最短路分別為infinite、60,找到v5,標記為1,以v5為中間點更新最短路表,此時沒有元素被更新
6.進入第五次迴圈,這次迴圈沒找到任何東西
7.退出迴圈,len表中即為v0到其餘各個節點的最短路徑。
以上就是dijkstra演算法最基本的思想,當然,在找最短路時我們常常會需要求出到達某點的最短路徑,那麼下面,我們就來看看要怎樣記錄下到達某點的最短路徑:
在dijkstra演算法的前提下加入查詢最短路徑其實很簡單,只要在每次更新最短路時儲存在該頂點的父節點序號即可,最後輸出時回退中間節點然後用堆疊輸出即可
Dijkstra演算法詳解
dijkstra演算法是由e.w.dijkstra於1959年提出,又叫迪傑斯特拉演算法,它應用了貪心演算法模式,是目前公認的最好的求解最短路徑的方法。演算法解決的是有向圖中單個源點到其他頂點的最短路徑問題,其主要特點是每次迭代時選擇的下乙個頂點是標記點之外距離源點最近的頂點。但由於dijkstra...
Dijkstra演算法詳解
迪傑斯特拉 dijkstra 演算法是典型最短路徑演算法,用於計算乙個節點到其他節點的最短路徑。它的主要特點是以起始點為中心向外層層擴充套件 廣度優先搜尋思想 直到擴充套件到終點為止 通過dijkstra計算圖g中的最短路徑時,需要指定起點s 即從頂點s開始計算 此外,引進兩個集合s和u。s的作用是...
Dijkstra演算法詳解
前幾天研究的bellman ford演算法雖然可以算負權,可是時間複雜度高達o nm 即使是採用了佇列優化,也有可能被網格圖卡回o nm 所以今天我們就來研究乙個新的,更快的,但同時只能在正權圖上執行的演算法 dijkstra 樸素dijkstra演算法 我們首先需要以下幾個陣列 dist,vis,...