求從start到end的最短路徑
涉及到無回環路徑的情況(A-》B、B-》A),可以使用dijkstra算法(狄克斯特拉)
算法步驟詳解:
1、找出“最便宜”的節點,即可在最短時間內到達的節點(從start出發,最短距離的節點)
2、更新通過該節點,到其他鄰居節點的最短距離
3、重復這個過程,直到對圖中的每個幾點都這樣做了
4、計算最短路徑
1、根據圖片各節點之間的距離,建立數據關系
graph表示各節點可達節點的距離
graph = {}
graph["start"] = {}
graph["start"]["A"] = 5
graph["start"]["B"] = 2
graph["A"] = {}
graph["A"]["C"] = 4
graph["A"]["D"] = 2
graph["B"] = {}
graph["B"]["A"] = 1
graph["B"]["E"] = 6
graph["C"] = {}
graph["C"]["end"] = 2
graph["D"] = {}
graph["D"]["end"] = 1
graph["E"] = {}
graph["E"]["D"] = 1
graph["E"]["end"] = 4
graph["end"] = {}
2、建立一個數據結構,用來存儲從start節點,到各個節點的距離,不知道距離的節點,先記做無窮大(math.inf)
infinity = math.inf
costs = {}
costs["A"] = 6
costs["B"] = 2
costs["C"] = infinity
costs["D"] = infinity
costs["E"] = infinity
costs["end"] = infinity
3、建立一個數據結構,用來存儲從start節點,到各個節點最短距離時,該節點的父節點
parents = {}
parents["A"] = "start"
parents["B"] = "start"
parents["C"] = None
parents["D"] = None
parents["E"] = None
parents["F"] = None
根據節點圖,初始化的3個數據結構已經創建完成
計算start到各個節點的最小距離,就可以按照算法步驟來完成
1、首先查找start節點出發可達的最小距離的節點返回該節點
#如果節點被檢查過,則添加到processed中
processed = []
def find_lowest_cost_node(costs):
lowest_cost = infinity #未檢查過的節點最小距離
lowest_cost_node = None #節點初始化
for node in costs: #遍歷節點
cost = costs[node] #返回start到節點的距離
if cost < lowest_cost and node not in processed: #如果節點距離小於最小距離,並且該節點沒有被檢查過,那么設置最小距離為當前被檢查的節點的最小距離,最小距離節點為當前檢查的節點
lowest_cost = cost
lowest_cost_node = node
return lowest_cost_node #返回最小節點
2、計算從start節點,經過最小距離節點到最小距離節點的鄰節點的距離,並更新相關數據結構。依次對剩余未檢查的節點進行遍歷
例如:start到B,最小距離為2,先檢查B節點,然后計算start經過B到B的鄰節點A、E的距離
start->B->A 的距離為2+1=3,小於start->A(6),所以,需要更新costs中start到A的最小距離為3,parents中,A的父節點為B
#首先找到最小距離的節點
node= find_lowest_cost_node(costs)
#當節點不為空時
while node is not None:
cost = costs[node] #start到node的距離
neighbors = graph[node] #node的鄰節點
for n in neighbors.keys(): #遍歷鄰節點
new_cost = cost + neighbors[n] #start經過node到鄰節點的距離
if costs[n] > new_cost: #判斷start經過node到鄰節點的距離與start到鄰節點的最小距離,如果小於就更新最小距離與父節點
costs[n] = new_cost
parents[n] = node
processed.append(node) #被檢查的節點添加到數組中
node = find_lowest_cost_node(costs) #遍歷
最終打印parents、costs,就可以知道從start到各個節點的最小距離以及最小距離的父節點
print(parents)
print(costs)
{'A': 'B', 'B': 'start', 'C': 'A', 'D': 'A', 'E': 'B', 'end': 'D'}
{'A': 3, 'B': 2, 'C': 7, 'D': 5, 'E': 8, 'end': 6}
從中可以看出start到end的最小距離為6,父節點關系:end->D->A->B->start(路徑為:start-B-A-D-end)