Dijkstra迪傑斯特拉演算法
用“Graph”作出簡圖:
圖例:
推導"選定起點"的Routing Table(路由表)
行號 | 節點 | 最短距離 | 前一節點 | 已訪問完全 |
---|---|---|---|---|
1 | A | 0 | ||
2 | B | 2 | A | T |
3 | C | 12 | F | T |
4 | D | 7 | B | T |
5 | E | 8 | B | T |
6 | F | 9 | D,E | T |
上表的用法:
- 表格的"第1行"是"起點"; 圖例:上表是圖上的節點"A"作為起點;
- 由"終點"起始,用"每一節點"查表得到的"前一節點";
一步步倒推,可得出 "起點" 到 "終點" 的 "最短完整路線".
例如:要求解“A點出發,到C點的最短路線”,
根據上表,可查表得出:- 終點"C"節點的資料記錄行的"行號"是 "3"(第3行),
- "最短路線" 為12(由"起點A"到"終點C"),
- "最短完整路線"("起點A"到"終點C"):
由終點C起始, 遞推的用"每一節點"查表得到的"前一節點", 一步步倒推, 可得出:
$ C \overset{3}{\leftarrow} F \overset{2}{\leftarrow} D \overset{5}{\leftarrow} B \overset{2}{\leftarrow} A $ - 注意:"最短路徑"可能有不只一條;
例如: "起點A"到"終點F"的"最短路線"(最短距離都為9)- $ F \overset{2}{\leftarrow} D \overset{5}{\leftarrow} B \overset{2}{\leftarrow} A $
- $ F \overset{1}{\leftarrow} E \overset{6}{\leftarrow} B \overset{2}{\leftarrow} A $
如何根據"節點路線Graph"得出"Routing Table(路由表)"
將 Graph 轉化為 Dictionary 資料結構:
例如圖示的 Graph 可轉化為:
MAX_DIST = 99999999
DIST_INDEX = 0
PREV_INDEX = 1
SOURCE = "A"
graph_dict = { # Graph 轉化為 Dictionary 資料結構
"A": [0, ["A"], ("B", 2), ("D", 8)],
"B": [MAX_DIST, [], ("A", 2), ("D", 5), ("E", 6)],
"C": [MAX_DIST, [], ("E", 9), ("F", 3)],
"D": [MAX_DIST, [], ("A", 8), ("B", 5), ("E", 3), ("F", 2)],
"E": [MAX_DIST, [], ("B", 6), ("D", 3), ("F", 1), ("C", 9)],
"F": [MAX_DIST, [], ("D", 2), ("E", 1), ("C", 3)],
}
queue_dict = {}
queue_dict[SOURCE] = graph_dict[SOURCE] # 開始只需要將初始"起點A"加入"任務佇列"
while len(queue_dict) > 0: # 需要更新計算“後繼”節點的"任務佇列"
(node, val) = result_dict.popitem() # 取出一個任務"節點"
(min_dist, prev, *edges) = val # 得到其"當前累加權重","前一個節點" 和 "其edges"
print("\n Processing : %r: min_dist:%d, prev:%r" % (node, min_dist, prev))
for next, weight in edges: # 迭代每一條 edge
next_val = graph_dict[next]
accu_dist = min_dist + weight # 由"當前節點" 計算 "下一節點" 的"累加權重"
if accu_dist < next_val[DIST_INDEX]: # 計算得出"更優"的"累加權重":
next_val[DIST_INDEX] = accu_dist # 將"更優"的"累加權重"更新到"下一節點"
next_val[PREV_INDEX] = [node] # "更優"選擇的"前一節點", 更新到"下一節點"
queue_dict[next] = next_val # 有更新的"下一節點"要加入"任務佇列"
print(
" Edge from:%r, to:%r, accu_dist:%d, prev:%r"
% (node, next, accu_dist, next_val[PREV_INDEX])
)
elif accu_dist == next_val[DIST_INDEX]: # 多個"前節點"有"同優"的"累加權重"
if node not in next_val[PREV_INDEX]:
next_val[PREV_INDEX].append(node) # 追加到"前節點"列表
print(
" Edge from:%r, to:%r, accu_dist:%d, prev:%r"
% (node, next, accu_dist, next_val[PREV_INDEX])
)
else:
print(" Edge from:%r, to:%r, accu_dist:%d, " % (node, next, accu_dist))
print("\n" + "#" * 10 + "\nRouting Table:\n") # 列印路由表
items = list(graph_dict.items())
for n, val in sorted(items, key=lambda x: x[0]):
print(
"Node:%r, accu_dist:% 2d, prev:%r" % (n, val[DIST_INDEX], val[PREV_INDEX])
)
執行結果:
root@localhost:~/storage/shared/AAAAA# python dijkstra.py
Processing : 'A': min_dist:0, prev:['A']
Edge from:'A', to:'B', accu_dist:2, prev:['A']
Edge from:'A', to:'D', accu_dist:8, prev:['A']
Processing : 'D': min_dist:8, prev:['A']
Edge from:'D', to:'A', accu_dist:16,
Edge from:'D', to:'B', accu_dist:13,
Edge from:'D', to:'E', accu_dist:11, prev:['D']
Edge from:'D', to:'F', accu_dist:10, prev:['D']
Processing : 'F': min_dist:10, prev:['D']
Edge from:'F', to:'D', accu_dist:12,
Edge from:'F', to:'E', accu_dist:11, prev:['D', 'F']
Edge from:'F', to:'C', accu_dist:13, prev:['F']
Processing : 'C': min_dist:13, prev:['F']
Edge from:'C', to:'E', accu_dist:22,
Edge from:'C', to:'F', accu_dist:16,
Processing : 'E': min_dist:11, prev:['D', 'F']
Edge from:'E', to:'B', accu_dist:17,
Edge from:'E', to:'D', accu_dist:14,
Edge from:'E', to:'F', accu_dist:12,
Edge from:'E', to:'C', accu_dist:20,
Processing : 'B': min_dist:2, prev:['A']
Edge from:'B', to:'A', accu_dist:4,
Edge from:'B', to:'D', accu_dist:7, prev:['B']
Edge from:'B', to:'E', accu_dist:8, prev:['B']
Processing : 'E': min_dist:8, prev:['B']
Edge from:'E', to:'B', accu_dist:14,
Edge from:'E', to:'D', accu_dist:11,
Edge from:'E', to:'F', accu_dist:9, prev:['E']
Edge from:'E', to:'C', accu_dist:17,
Processing : 'F': min_dist:9, prev:['E']
Edge from:'F', to:'D', accu_dist:11,
Edge from:'F', to:'E', accu_dist:10,
Edge from:'F', to:'C', accu_dist:12, prev:['F']
Processing : 'C': min_dist:12, prev:['F']
Edge from:'C', to:'E', accu_dist:21,
Edge from:'C', to:'F', accu_dist:15,
Processing : 'D': min_dist:7, prev:['B']
Edge from:'D', to:'A', accu_dist:15,
Edge from:'D', to:'B', accu_dist:12,
Edge from:'D', to:'E', accu_dist:10,
Edge from:'D', to:'F', accu_dist:9, prev:['E', 'D']
##########
Routing Table:
Node:'A', accu_dist: 0, prev:['A']
Node:'B', accu_dist: 2, prev:['A']
Node:'C', accu_dist: 12, prev:['F']
Node:'D', accu_dist: 7, prev:['B']
Node:'E', accu_dist: 8, prev:['B']
Node:'F', accu_dist: 9, prev:['E', 'D']