《演算法圖解》總結第 7 章:狄克斯特拉演算法
僅用於記錄學習,歡迎批評指正,大神勿噴
系列文章目錄
《演算法圖解》總結第 1 章:二分查詢、大O表示法; 《演算法圖解》總結第 2 章:陣列和連結串列,選擇排序; 《演算法圖解》總結第3章:while迴圈、遞迴、棧; 《演算法圖解》總結第4章:分而治之、快速排序; 《演算法圖解》總結第5章:雜湊表; 《演算法圖解》總結第6章:廣度優先搜尋狄克斯特拉演算法
廣度優先搜尋找出的是非加權圖中段數最少的路徑,狄克斯特拉演算法找出的是加權圖中最快(短)的路徑。
狄克斯特拉演算法包含四個步驟:
(1)找出“最便宜”的節點,即可在最短時間內到達的節點;
(2)更新該節點的鄰居的開銷;
(3)重複這個過程,直到對圖中的每個節點都這樣做了;
(4)計算最終路徑。
狄克斯特拉演算法只適用於有向無環圖(DAG)。
如果有負權邊,就不能使用狄克斯特拉演算法,因為負權邊會導致這種演算法不管用,以下圖為例:
假設要用樂譜換架子鼓,因為5>0,所以第一步找出的“最便宜”的點是海報,更新其鄰居的開銷。
第二步找出“最便宜”的未處理節點:黑膠唱片
從此圖看出來海報節點也更新了開銷,但是第一步海報節點已經處理過了,這是一個危險訊號,因為節點一旦被處理,就意味著沒有前往該節點的更便宜的途徑,但是我們卻找到了前往海報更便宜的途徑。
架子鼓沒有任何鄰居,演算法結束,因此最終開銷如下:
由此可以得出樂譜換架子鼓的開銷為35美元,但是從圖中可以看出有一種交換方式為33美元,但是狄克斯特拉演算法沒有找到。為什麼呢?理由:狄克斯特拉演算法的假設是:對於處理過的海報節點,沒有前往該節點的更短路徑。這種假設僅在沒有負權邊時才成立。如果要找出在包含負權邊的圖中找出最短路徑,可使用另一種演算法:貝爾曼-福德演算法。
應用案例
案例:運用狄克斯特拉演算法找出下圖從起點到終點的最快路徑。
案例分析
要解決這個問題的程式碼,需要三個雜湊表:加權圖、開銷表、父節點表。
準備工作
一、表示加權圖:
graph = {}
graph["start"] = {}
graph["start"]["a"] = 6
graph["start"]["b"] = 2
graph["a"] = {}
graph["a"]["final"] = 1
graph["b"] = {}
graph["b"]["a"] = 3
graph["b"]["final"] = 5
graph["final"] = {}
二、 用雜湊表來儲存每個節點的開銷,即建立開銷圖
infinity = float("inf") # 表示無窮大
costs = {}
costs["a"] = 6
costs["b"] = 2
costs["final"] = infinity # 到終點的開銷為無窮大
三、建立儲存父節點的雜湊表
parents = {}
parents["a"] = "start"
parents["b"] = "start"
parents["final"] = None
四、 建立陣列,用於記錄處理過的節點
processed = []
五、定義開銷最小的節點
def find_lowest_cost_node(costs):
lowest_cost = float("inf")
lowest_cost_node = None
# 遍歷所有節點
for node in costs:
cost = costs[node]
# 如果當前節點的開銷更低且未處理過
if cost < lowest_cost and node not in processed:
# 就將其視為開銷最低的節點
lowest_cost = cost
lowest_cost_node = node
return lowest_cost_node
實現狄克特斯拉演算法
# 在未處理的節點中找出開銷最小的節點
node = find_lowest_cost_node(costs)
# while迴圈在所有節點都被處理過後結束
while node is not None:
cost = costs[node]
neighbors = graph[node]
# 遍歷當前節點的所有鄰居
for n in neighbors.keys():
new_cost = cost + neighbors[n]
# 如果經當前節點前往該鄰居更近
if costs[n] > new_cost:
# 更新該鄰居的開銷
costs[n] = new_cost
# 同時將該鄰居的父節點設定為當前節點
parents[n] = node
# 將當前節點標記為處理過
processed.append(node)
# 找出接下來要處理的節點,並迴圈
node = find_lowest_cost_node(costs)
print("Cost from the start to each node:")
print(costs)
輸出結果:
Cost from start to each node:
{'a': 5, 'b': 2, 'final': 6}
相關文章
- 演算法(四):圖解狄克斯特拉演算法演算法圖解
- 資料結構與演算法——迪傑斯特拉(Dijkstra)演算法資料結構演算法
- 你已經是個成熟的程式設計師了,該學會用程式幫自己省錢了————狄克斯特拉演算法程式設計師演算法
- 資料結構學習筆記-迪傑斯特拉演算法資料結構筆記演算法
- 最短路徑—Dijkstra(迪傑斯特拉)演算法演算法
- 求最短路徑-----迪傑斯特拉演算法演算法
- dijkstra迪傑斯特拉演算法(鄰接表法)演算法
- 路徑規劃演算法 - 求解最短路徑 - Dijkstra(迪傑斯特拉)演算法演算法
- C++迪傑斯特拉演算法求最短路徑的詳細解釋C++演算法
- 資料結構與演算法——克魯斯卡爾(Kruskal)演算法資料結構演算法
- 【演算法圖解】讀書筆記:第3章 遞迴演算法圖解筆記遞迴
- 程式設計師必須會的基本演算法8-Dijkstra演算法(迪傑斯特拉演算法)程式設計師演算法
- 狄利克雷卷積 & 莫比烏斯反演卷積
- 7.10 第7章小結
- 狄利克雷卷積與莫比烏斯反演卷積
- 圖的演算法的總結演算法
- 《JavaScript資料結構與演算法》筆記——第7章 字典和雜湊表JavaScript資料結構演算法筆記
- 演算法導論-第6章演算法
- 《啊哈!演算法》-第 2 章:棧、佇列、連結串列演算法佇列
- 最小生成樹(克魯斯卡爾演算法)資料結構演算法資料結構
- 迪傑斯特拉與spfa
- 字串模式匹配--布魯特.福斯演算法視訊講解字串模式演算法
- 《JavaScript資料結構與演算法》筆記——第3章 棧JavaScript資料結構演算法筆記
- 《JavaScript資料結構與演算法》筆記——第6章 集合JavaScript資料結構演算法筆記
- 最短路-迪傑斯特拉(dijkstra)
- 圖論(三)--各種基礎圖演算法總結圖論演算法
- 最小生成樹---普里姆演算法(Prim演算法)和克魯斯卡爾演算法(Kruskal演算法)演算法
- 《JavaScript資料結構與演算法》筆記——第4章 佇列JavaScript資料結構演算法筆記佇列
- 《JavaScript資料結構與演算法》筆記——第2章 陣列JavaScript資料結構演算法筆記陣列
- 一句話總結 7 種搜尋演算法演算法
- 演算法思路總結演算法
- KMP演算法和bfprt演算法總結KMP演算法
- 推薦演算法(二)--演算法總結演算法
- 資料結構與演算法-圖解版資料結構演算法圖解
- 演算法(八):圖解KNN演算法演算法圖解KNN
- 統計學習方法第二十章作業:潛在狄利克雷分配 LDA 吉布斯抽樣法演算法 程式碼實現LDA演算法
- 第3章 區塊鏈骨骼:密碼演算法區塊鏈密碼演算法
- 『演算法』之 初級排序演算法總結演算法排序