算法比较
- 相比于第6章的广度优先算法计算的是无权图中的最短路径,狄克特斯拉算法计算的是加权图中的最短路径
算法流程
- 找出最便宜的节点,即可在最短时间内前往的节点。
- 对于该节点的邻居,检查是否有前往它们的更短路径,如果有,就更新其开销。
- 重复这个过程,直到对图中的每个节点都这样做了。
- 计算最终路径
注意事项
- 迪杰斯特拉适用于有向无环图,因为无向或者有环,在该算法中,你会发现它会不断的循环,因为一直有邻居。
- 该算法不适用于负权边,负权边的意思就是边的权重为负值。原因在于,算法本身考虑的是当前最小的cost的节点A,跳转到A节点进行下一步,如果计算完A节点的所有邻居后,根据cost的表选择另外一个节点B,从B到A权重为负值,也就意味着,A节点在cost中的值可以被更新,但是算法已经将节点A剔除。
代码讲解
上图中,左图是我们要解决的问题,首先我们需要用的是构建三个散列表,下面详细看代码
#author:ErenCoder
#构建图
graph={}
graph["start"]={}
graph["start"]['a']=6
graph['start']['b']=2
graph['a']={}
graph['a']['fin']=1
graph['b']={}
graph['b']['a']=3
graph['b']['fin']=5
graph['fin']={}
#构建cost表
infinity=float('inf')
costs={}
costs['a']=6
costs['b']=2
costs['fin']=infinity
#构建parents表
parents={}
parent['a']='start'
parent['b']='start'
parent['fin']=None
#记录处理过的节点
processed=[]
#在未处理的节点中找出开销最小的节点
node=find_lowest_cost_node(costs)
#这个while循环在所有节点都被处理过后结束
while node is not None:
cost=costs[node]
neighbors=graph[node]
#遍历当前节点的所有邻居
for n in neighbors.keys():
#更新节点n的cost值
new_cost=cost+neighbors[n]
#如果经当前节点前往该邻居更近,就更新该邻居的开销
if costs[n]>new_cost:
costs[n]=new_cost
#同时将该邻居的父节点设置为当前节点
parents[n]=node
#将当前节点标记为处理过
processed.append(node)
找出接下来要处理的节点,并循环
node=find_lowest_cost_node(costs)
def find_lowest_cost_node(costs):
lowest_cost=float('inf')
lowest_cost_node=None
#遍历所有的节点
for node in costs:
cost=costs[node]
#如果当前节点的开销更低且未处理过
if cost<lowest_cost and node not in processed:
lowest_cost=cost
lowest_cost_node=node
return lowest_cost_node
大家如果有不理解的欢迎随时交流,freestyle