Dijkstra迪杰斯特拉算法
图例:
行号 | 节点 | 最短距离 | 前一节点 | 已访问完全 |
---|---|---|---|---|
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 \leftarrow F \leftarrow D \leftarrow B \leftarrow A $ - 注意:"最短路径"可能有不只一条;
例如: "起点A"到"终点F"的"最短路线"- $ F \leftarrow D \leftarrow B \leftarrow A $
- $ F \leftarrow E \leftarrow B \leftarrow A $
如何根据"节点路线Graph"得出"路由表"
-
将 Graph 转化为 Dictionary 数据结构:存储全部的"每一节点"到其"下一节点"映射;
例如图示的 Graph 可转化为:MAX_DIST = 99999999 DIST_INDEX = 0 PREV_INDEX = 1 SOURCE = "A"graph_dict = {"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)], }result_dict = {} result_dict[SOURCE] = graph_dict[SOURCE]while len(result_dict) > 0:(node, val) = result_dict.popitem()(min_dist, prev, *edges) = valprint("\n Processing : %r: min_dist:%d, prev:%r" % (node, min_dist, prev))for next, weight in edges:next_val = graph_dict[next]accu_dist = min_dist + weightif accu_dist < next_val[DIST_INDEX]:next_val[DIST_INDEX] = accu_distnext_val[PREV_INDEX] = [node]result_dict[next] = next_valprint(" 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 + "\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]))
-
选定Graph图上的节点"A"作为起点,