狄克斯特拉算法的用途:
用于在加权图中查找最短路径,但是只能使用在权重为正的图中,如果存在负权边,结果就会出现错误。(负权边可以使用贝尔曼-福德算法)
狄克斯特拉算法的基本步骤:
1.找出“最便宜”的节点,即可在最短时间内到达的节点。
2.更新该节点的邻居的开销。
3.重复这个过程,直到对图中的每个节点都这样做了。
4.计算最终路径。
解析基本步骤:
1.从起点开始,比较所有(起点->起点的邻居)的最短距离,找出该邻居节点A。
2.从该邻居节点A开始,计算该节点A到其所有邻居的距离并与原先的距离比较,记录较小的距离,更新
3.然后划去已经计算过所有邻居的节点,然后从没有划去的剩余节点中找到最小距离的节点,从该节点开始,计算该节点到其所有邻居的距离并与原先的距离比较,记录较小的距离,更新
4.然后划去已经计算过所有邻居的节点,然后从没有划去的剩余节点中找到最小距离的节点,从该节点开始,计算该节点到其所有邻居的距离并与原先的距离比较,记录较小的距离,更新
5.重复4
6.直到所有的节点都已经划去,结束
狄克斯特拉算法实例:
graph是描述图的散列表
graph = {'start' : {'a' : 6 , 'b' : 2} , 'a' : {'fin' : 1} , 'b' : {'a' : 3 , 'fin' : 5}}
costs是记录最短距离的散列表
costs = {'a' : 6 , 'b' : 2 , 'fin' : infinity}
parents是记录该节点的父节点的散列表
parents = {'a' : 'start' , 'b' : 'start' , 'fin' : None}
processed是记录已经被遍历过该节点所有邻居的节点
processed = []
过程如下:
从起点开始,起点到其所有邻居的距离2和6是初始值,其他不相邻的节点的距离为无穷大,然后从{2,6,无穷大}中找到最小值2,2对应的节点是B,然后从B开始遍历B的所有邻居{A,终点},计算起点->B->A的距离为2+3=5,比之前的距离6要小,所以更新A的记录为5,继续计算起点->B->终点的距离为2+5=7,比之前的距离无穷大要小,所以更新终点的记录为7,至此B的所有相邻节点遍历完毕,故划去B,之后继续从{2,5,7}中寻找最小值,由于2对应的B节点已经被划去,所以只要从{5,7}中找最小值,最小值为5,5对应于节点A,然后从A开始遍历A的所有邻居{终点},计算起点->A->终点的距离6,比之前的距离7要小,故更新终点的记录为6,至此A的所有邻居遍历完毕,故划去A,最后只剩下终点这个节点,由于终点没有邻居,故图中的所有邻居遍历完毕。至此得出从起点到终点的最短距离是6。
代码如下:
1 infinity = float('inf')
2 graph = {'start':{'a':6,'b':2},'a':{'fin':1},'b':{'a':3,'fin':5},'fin':{}}
3 costs = {'a':6,'b':2,'fin':infinity}
4 parents = {'a':'start','b':'start','fin':None}
5 processed = []
6
7
8 def main(graph,costs,parents,processed,infinity):
9 node = find_lowest_cost_node(costs,processed)
10 while node is not None:
11 for n in graph[node].keys():
12 new_cost = costs[node] + graph[node][n]
13 if costs[n] > new_cost:
14 costs[n] = new_cost
15 parents[n] = node
16 processed.append(node)
17 node = find_lowest_cost_node(costs,processed)
18
19 def find_lowest_cost_node(costs,processed):
20 lowest_cost = float('inf')
21 lowest_cost_node = None
22 for node in costs:
23 if lowest_cost > costs[node] and node not in processed:
24 lowest_cost = costs[node]
25 lowest_cost_node = node
26 return lowest_cost_node
27
28 main(graph,costs,parents,processed,infinity)
29 print(costs)
30 print(parents)
运算结果如下: