算法比較
- 相比於第6章的廣度優先算法計算的是無權圖中的最短路徑,狄克特斯拉算法計算的是加權圖中的最短路徑
算法流程
- 找出最便宜的節點,即可在最短時間內前往的節點。
- 對於該節點的鄰居,檢查是否有前往它們的更短路徑,如果有,就更新其開銷。
- 重複這個過程,直到對圖中的每個節點都這樣做了。
- 計算最終路徑
注意事項
- 迪傑斯特拉適用於有向無環圖,因爲無向或者有環,在該算法中,你會發現它會不斷的循環,因爲一直有鄰居。
- 該算法不適用於負權邊,負權邊的意思就是邊的權重爲負值。原因在於,算法本身考慮的是當前最小的cost的節點A,跳轉到A節點進行下一步,如果計算完A節點的所有鄰居後,根據cost的表選擇另外一個節點B,從B到A權重爲負值,也就意味着,A節點在cost中的值可以被更新,但是算法已經將節點A剔除。
代碼講解
上圖中,左圖是我們要解決的問題,首先我們需要用的是構建三個散列表,下面詳細看代碼
#author:ErenCoder
#構建圖
graph={}
graph["start"]={}
graph["start"]['a']=6
graph['start']['b']=2
graph['a']={}
graph['a']['fin']=1
graph['b']={}
graph['b']['a']=3
graph['b']['fin']=5
graph['fin']={}
#構建cost表
infinity=float('inf')
costs={}
costs['a']=6
costs['b']=2
costs['fin']=infinity
#構建parents表
parents={}
parent['a']='start'
parent['b']='start'
parent['fin']=None
#記錄處理過的節點
processed=[]
#在未處理的節點中找出開銷最小的節點
node=find_lowest_cost_node(costs)
#這個while循環在所有節點都被處理過後結束
while node is not None:
cost=costs[node]
neighbors=graph[node]
#遍歷當前節點的所有鄰居
for n in neighbors.keys():
#更新節點n的cost值
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)
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
大家如果有不理解的歡迎隨時交流,freestyle