迪杰斯特拉算法
该算法用于求解单源最短路径问题
import heapq
graph = {
"A": {"B": 5, "C": 1},
"B": {"A": 5, "C": 2, "D": 1},
"C": {"A": 1, "B": 2, "D": 4, "E": 8},
"D": {"B": 1, "C": 4, "E": 3, "F": 6},
"E": {"C": 8, "D": 3},
"F": {"D": 6},
}
def __init_path_information(graph, start):
distance = dict.fromkeys(graph.keys(), float("inf"))
parent = dict.fromkeys(graph.keys(), None)
for vertex in graph[start].keys():
distance[vertex] = graph[start][vertex]
parent[vertex] = start
distance[start] = 0
return distance, parent
def dijkstra(graph, start):
priority_queue = []
distance, parent = __init_path_information(graph, start)
seen = dict.fromkeys(graph.keys(), False)
heapq.heappush(priority_queue, (distance[start], start))
while priority_queue:
dist, vertex = heapq.heappop(priority_queue)
seen[vertex] = True
neighbors = graph[vertex].keys()
for neighbor in neighbors:
if not seen[neighbor]:
if dist + graph[vertex][neighbor] < distance[neighbor]:
distance[neighbor] = dist + graph[vertex][neighbor]
parent[neighbor] = vertex
heapq.heappush(priority_queue, (distance[neighbor], neighbor))
return parent, distance
if __name__ == "__main__":
parent, distance = dijkstra(graph, "A")
print(parent, distance, sep="\n")
运行结果如下:
上述代码看上去比较符合直觉,但其实还有优化的空间,因为只有当节点出队时,该节点才能被认为已经求得了最短路径。若对于某一节点,如果没有求出该节点的最短路,该节点就会一直入队,从而很可能会出现相同节点重复入队的现象 。为避免这一现象可将代码优化如下:
import heapq
graph = {
"A": {"B": 5, "C": 1},
"B": {"A": 5, "C": 2, "D": 1},
"C": {"A": 1, "B": 2, "D": 4, "E": 8},
"D": {"B": 1, "C": 4, "E": 3, "F": 6},
"E": {"C": 8, "D": 3},
"F": {"D": 6},
}
def dijkstra(graph, start):
priority_queue = []
distance = dict.fromkeys(graph.keys(), float("inf"))
distance[start] = 0
parent = {start: None}
seen = dict.fromkeys(graph.keys(), False)
heapq.heappush(priority_queue, (distance[start], start))
while priority_queue:
dist, vertex = heapq.heappop(priority_queue)
seen[vertex] = True
neighbors = graph[vertex].keys()
for neighbor in neighbors:
if not seen[neighbor]:
if dist + graph[vertex][neighbor] < distance[neighbor]:
distance[neighbor] = dist + graph[vertex][neighbor]
parent[neighbor] = vertex
heapq.heappush(priority_queue,
(distance[neighbor], neighbor))
return parent, distance
if __name__ == "__main__":
parent, distance = dijkstra(graph, "A")
print(parent, distance, sep="\n")
运行结果如下,同样能得到正确的答案