如上图,要找到从A点到D点,最便宜的路径。
代码如下:
from collections import deque
# 定义children表,用来记录每个节点的孩子节点是谁
children = dict()
children['a'] = ['b', 'e']
children['b'] = ['c', 'f']
children['e'] = ['c', 'f']
children['c'] = ['d']
children['f'] = ['d']
children['d'] = []
# 定义farthers表,用来记录每个节点的爸爸节点是谁
farthers = dict()
farthers['a'] = [['a', 0]]
farthers['b'] = [['a', 5]]
farthers['e'] = [['a', 0]]
farthers['c'] = [['b', 15], ['e', 30]]
farthers['f'] = [['b', 20], ['e', 35]]
farthers['d'] = [['c', 20], ['f', 10]]
infinity = float('inf')
# 定义最低费用表,用来记录从起点到每个点的最低费用是多少。这个表是狄克斯特拉算法的关键所在。
# 它的元素的值是一个列表,列表的第一个值记录这个节点花费最便宜的爸爸节点的名字,第二个值记录从起点到这个节点最便宜的费用
lowest_cost = dict()
# 定义队列my_deque,用来记录从起点到终点依次要计算的点
my_deque = deque()
start = 'a'
finish = 'd'
my_deque += start
# 定义距终点费用最便宜的爸爸节点为自己,费用为0
lowest_cost[start] = [start, 0]
# 暂定距终点费用最便宜的爸爸节点为none,费用为无穷大。
lowest_cost[finish] = ['none', infinity]
searched = []
# 只要列表不为空,就一直往下计算费用
while my_deque:
location = my_deque.popleft()
if location not in searched:
my_deque += children[location]
# 定义costs,是用来记录当前节点的所有父亲节点的名字和费用
costs = []
for farther in farthers[location]:
name = farther[0]
# 费用 = 它爸爸到它的费用 + 它爸爸到起点的费用
cost = farther[1] + lowest_cost[name][1]
costs.append([name, cost])
# 按照费用对列表内的父亲节点进行排序
costs.sort(key=lambda node: node[1])
# 取费用最低的父亲节点,写进最低费用表
lowest_cost[location] = costs[0]
# 如果当前节点为终点,则打印最低费用,并退出循环
if location == finish:
print('最低费用为', lowest_cost[finish][1])
break
# 定义path,用来记录最低费用的路径
path = []
# 从终点开始往前回溯,直到起点
while finish != start:
baba = lowest_cost[finish][0]
finish = baba
# 这里path记录的值,是从终点到起点的路径
path.append(baba)
# 将path反转,使其元素依次为从起点到终点的路径,符合人的习惯
path.reverse()
print('路径依次为:', path)
运行结果如下: