迪杰斯特拉算法(Dijkstra's algorithm)是一种解决带权有向图(或无向图)中单源最短路径(single-source shortest path)问题的贪心算法。它通过选定尚未确定最短路径的顶点中距离最小的顶点来扩展已确定最短路径的顶点集合,以此不断向图中的其他顶点扩展最短路径,直到扩展至终点或无法继续扩展为止。
目录
1、实现步骤
2、程序代码
3、运行结果
1、实现步骤
- 初始化:将源点的距离设为零,所有其他点的距离设为无穷大。
- 将源点加入到一个优先队列中,队列中元素的优先级根据距离排序,距离越小,优先级越高。
- 对于队列中的每个顶点,遍历它所有的邻居节点,并计算从源点到邻居节点的距离。如果这个距离比邻居节点已有的距离更短,更新邻居节点的距离,并将邻居节点加入到优先队列中。
- 标记当前顶点为已访问。
- 重复步骤3-4,直到优先队列为空或者找到目标节点。
- 如果找到目标节点,则可以通过反向查找每个节点的父节点,确定起点到目标节点的最短路径。
2、程序代码
#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
@author: ewb
"""
# 定义节点类
class Node:
def __init__(self, name):
self.name = name
self.neighbours = {}
self.distance = float("inf")
self.visited = False
self.parent = None
def add_neighbour(self, neighbour, weight=0):
self.neighbours[neighbour] = weight
def get_neighbours(self):
return self.neighbours.keys()
# 定义图类
class Graph:
def __init__(self):
self.nodes = {}
def add_node(self, node):
self.nodes[node.name] = node
def get_node(self, name):
if name in self.nodes:
return self.nodes[name]
else:
return None
def add_edge(self, start, end, weight=0):
if start not in self.nodes:
self.add_node(Node(start))
if end not in self.nodes:
self.add_node(Node(end))
self.nodes[start].add_neighbour(self.nodes[end], weight)
self.nodes[end].add_neighbour(self.nodes[start], weight)
def get_nodes(self):
return self.nodes.keys()
def reset_nodes(self):
for node in self.nodes.values():
node.distance = float("inf")
node.visited = False
node.parent = None
# 定义迪杰斯特拉算法函数
def dijkstra(start_node, end_node):
start_node.distance = 0
queue = [start_node]
while queue:
node = queue.pop(0)
node.visited = True
for neighbour in node.get_neighbours():
if not neighbour.visited:
new_distance = node.distance + node.neighbours[neighbour]
if new_distance < neighbour.distance:
neighbour.distance = new_distance
neighbour.parent = node
queue.append(neighbour)
path = [end_node]
# 如果存在父节点
if end_node.parent:
while end_node.parent != start_node:
path.append(end_node.parent)
end_node = end_node.parent
path.append(start_node)
path.reverse()
return path
if __name__ == '__main__':
# 测试
graph = Graph()
graph.add_edge("A", "B", 7)
graph.add_edge("B", "C", 8)
graph.add_edge("B", "E", 7)
graph.add_edge("A", "D", 5)
graph.add_edge("D", "F", 6)
graph.add_edge("F", "G", 11)
# 开始节点
start_node = graph.get_node("A")
# 结束节点
end_node = graph.get_node("F")
path = dijkstra(start_node, end_node)
print("节点{}到节点{}:\n最短距离为:{}\n最短路径为:".format(start_node.name, end_node.name, end_node.distance), end=" ")
for index, node in enumerate(path):
if index < len(path) - 1:
print(node.name, ">", end=" ")
else:
print(node.name, end=" ")