1. 程式人生 > >【算法】狄克斯特拉算法(Dijkstra’s algorithm)

【算法】狄克斯特拉算法(Dijkstra’s algorithm)

父節點 定義 cte 最短路 pan 函數 dijk 節點 表示

狄克斯特拉算法(Dijkstra’s algorithm)

找出最快的路徑使用算法——狄克斯特拉算法(Dijkstra’s algorithm)。

使用狄克斯特拉算法

步驟

(1) 找出最便宜的節點,即可在最短時間內前往的節點。

(2) 對於該節點的鄰居,檢查是否有前往它們的更短路徑,如果有,就更新其開銷。

(3) 重復這個過程,直到對圖中的每個節點都這樣做了。

(4) 計算最終路徑。

術語

權重(weight):

狄克斯特拉算法用於每條邊都有關聯數字的圖,這些數字稱為權重(weight)。

加權圖/非加權圖(weighted graph)

帶權重的圖稱為加權圖( weighted graph),不帶權重

的圖稱為非加權圖(unweighted graph)。

要計算非加權圖中的最短路徑,可使用廣度優先搜索。要計算加權圖中的最短路徑,可使用狄克斯特拉算法。

可從一個節點出發,走一圈後又回到這個節點。

無向圖意味著兩個節點彼此指向對方,其實就是環!

狄克斯特拉算法只適用於有向無環圖(directed acyclicgraph,DAG)。

負權邊

不能將狄克斯特拉算法用於包含負權邊的圖

狄克斯特拉算法這樣假設:對於處理過的海報節點,沒有前往該節點的更短路徑。這種假設僅在沒有負權邊時才成立。

實現

示例:求起點到終點的最短路徑

技術分享圖片

#創建所有節點和路徑的散列表
graph={‘start‘: {‘a‘: 6, ‘b‘: 2}, ‘a‘: {‘fin‘: 1}, ‘b‘: {‘a‘: 3, ‘fin‘: 5}, ‘fin‘: {}}  

#創建已知節點花銷的散列表
costs={‘a‘: 6, ‘b‘: 2, ‘fin‘: float("inf")}  #float(‘inf‘) 表示正無窮                                       

#儲存父節點的散列表
parents={‘a‘: ‘start‘, ‘b‘: ‘start‘, ‘fin‘: 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 node is not None:                     #這個while循環在所有節點都被處理過後結束
    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(parents)

  

小結

  • 廣度優先搜索用於在非加權圖中查找最短路徑
  • 狄克斯特拉算法用於在加權圖中查找最短路徑
  • 僅當權重為正時狄克斯特拉算法才管用。
  • 如果圖中包含負權邊,請使用貝爾曼福德算法

【算法】狄克斯特拉算法(Dijkstra’s algorithm)