指定某两点之间求最短路
class Dijkstra:
def __init__(self, graph, start, goal):
self.graph = graph # 邻接表
self.start = start # 起点
self.goal = goal # 终点
self.temporary = {} # temporary 节点集合
self.permanent = {} # permanent 节点集合
self.temporary[start] = 0.0 # 将起点放入 temporary 中
self.parent = {start: None} # 存储节点的父子关系。键为子节点,值为父节点。方便做最后路径的回溯
self.min_dis = None # 最短路径的长度
def shortest_path(self):
while True:
if self.temporary is None:
print('搜索失败, 结束!')
break
distance, min_node = min(zip(self.temporary.values(), self.temporary.keys())) # 取出距离最小的节点
self.temporary.pop(min_node) # 将其从 temporary 中去除
self.permanent[min_node] = distance # 将节点加入 permanent 中
if min_node == self.goal: # 如果节点为终点
self.min_dis = distance
shortest_path = [self.goal] # 记录从终点回溯的路径
father_node = self.parent[self.goal]
while father_node != self.start:
shortest_path.append(father_node)
father_node = self.parent[father_node]
shortest_path.append(self.start)
print(shortest_path[::-1]) # 逆序
print('最短路径的长度为:{}'.format(self.min_dis))
print('找到最短路径, 结束!')
return shortest_path[::-1], self.min_dis # 返回最短路径和最短路径长度
for node in self.graph[min_node].keys(): # 遍历当前节点的邻接节点
if node not in self.permanent.keys(): # 邻接节点不在 permanent 中
if node in self.temporary.keys(): # 如果节点在 temporary 中
if self.graph[min_node][node] + distance < self.temporary[node]:
self.temporary[node] = distance + self.graph[min_node][node] # 更新节点的值
self.parent[node] = min_node # 更新继承关系
else: # 如果节点不在 temporary 中
self.temporary[node] = distance + self.graph[min_node][node] # 计算节点的值,并加入 temporary 中
self.parent[node] = min_node # 更新继承关系
if __name__ == '__main__':
g = {'1': {'2': 2, '3': 8, '4': 1}, # 无向图 每个节点的相邻节点都要输入
'2': {'1': 2, '3': 6, '5': 1},
'3': {'1': 8, '2': 6, '4': 7, '5': 5, '6': 1, '7': 2},
'4': {'1': 1, '3': 7, '7': 9},
'5': {'2': 1, '3': 5, '6': 3, '8': 2, '9': 9},
'6': {'3': 1, '5': 3, '7': 4, '9': 6},
'7': {'3': 2, '4': 9, '6': 4, '9': 3, '10': 1},
'8': {'5': 2, '9': 7, '11': 9},
'9': {'5': 9, '6': 6, '7': 3, '10': 1, '11': 2},
'10': {'7': 1, '9': 1, '11': 4},
'11': {'8': 9, '9': 2, '10': 4}
}
start = '1' # 指定起点
goal = '11' # 指定终点
dijk = Dijkstra(g, start, goal)
dijk.shortest_path()