沒事擼點演算法——dijkstra演算法(python)
阿新 • • 發佈:2018-12-18
資料結構地提出是為了更好地解決資料儲存問題,圖資料結構的提出是為了解決生活中的複雜網路問題。
在Python中,圖的表示方式一般使用字典以及列表完成。
#使用字典列表展現圖
graph={
1:{2:1,3:12},
2:{3:9,4:3},
3:{5:5},
4:{3:4,5:13,6:15},
5:{6:4},
6:{6:0}
}
Dijkstra演算法一般是用於解決求解最短路徑問題,屬於盲目搜尋演算法。
原理:不斷求解起始節點到其他節點的最短路徑成本。
First:
引入cost字典,表示對於起始點到每一個其他節點的成本。eg:cost[2]=1。表示起始點(這裡設定為節點1)到節點2的成本需要1。
引入visted列表,記錄已訪問的節點。eg:起始visted=[1];
引入Parents字典,記錄已求解最短路徑節點的前一個節點。eg:假設至3節點的最短路徑為1-2-4-3,則parents[3]=4;
Second:演算法流程(以上面的網路圖為例)
cost初始值為1節點到各個節點的成本
1 | 2 | 3 | 4 | 5 | 6 |
0 | 1 | 12 | 999(無窮) | 999(無窮) | 999(無窮) |
可以得出1-2的最短路徑成本即為1。因為1節點到2節點僅有一條路徑最短,如果1節點先到其他節點之後再返回2節點,必然成本大於1,所以1-2為2節點的最低成本路徑。此時將2節點放置visted中。
接下來,由於節點2已經解出1-2的最短路徑,計算2節點的出度(2-3,2-4)由1-2-3和1-2-4的成本分別為10、4小於之前的成本12、999,對cost字典進行更新。
1 | 2 | 3 | 4 | 5 | 6 |
0 | 1 | 10 | 4 | 999 | 999 |
此時,cost成本最小的為節點4,最短路徑為1-2-4,將4放入visted列表中,記錄parents[4]=2。
再看4的出度,對cost列表進行更新,尋找成本最小節點,記入visted列表中,同時記錄當前最短路徑節點的前一個節點,知道所有節點全部被訪問,即全部進入visted列表中,結束演算法。
全部程式碼:
# -*- coding: utf-8 -*-
"""
Created on Tue Oct 30 08:46:14 2018
@author: 24367
"""
# find the shortest node(not visted) to add in the list(visted)
def find_shortest_node(cost):
minDist=999
node=None
for item in cost.keys():
if (cost[item]<minDist)&(item not in visted):
minDist=cost[item]
node=item
return node
#Create Graph for the route plan
graph={
1:{2:1,3:12},
2:{3:9,4:3},
3:{5:5},
4:{3:4,5:13,6:15},
5:{6:4},
6:{6:0}
}
#記錄初始權值
cost={1:0,2:1,3:12,4:999,5:999,6:999}
#記錄當前最短路徑的前一個節點
parents={1:None,2:1,3:2,4:2,5:3,6:5}
#記錄已經訪問過的節點
visted=[1]
node=find_shortest_node(cost)
while (node):
for i in graph[node]:
newCost=cost[node]+graph[node][i];
if(newCost<cost[i]):
#更新cost權值以及記錄最短路徑前節點
cost[i]=newCost
parents[i]=node
visted.append(node)#將最短路徑節點新增至已訪問列表中
node=find_shortest_node(cost)
#輸出最短路徑
parent=parents[6]
while(parent):
print(parent)
parent=parents[parent]