对于 Dijkstra 算法,跟踪和存储每条最短路径包含的顶点的方法是什么?
For Dijkstra's algorithm, what would be a way to keep track of and store the vertices that each shortest path contains?
我把它编码出来以更新边的所有成本等,以完成 Dijkstra 的主要目标,即找到从源顶点到所有其他顶点的最短路径。
但我需要帮助的是找出一种方法,将每条最短路径包含的顶点存储到一个数组中,该数组包含它经过的每条路径的顶点。
例如,假设从源顶点 (A) 到顶点 (Z) 的最短路径是
A -> B -> V -> Z。最短路径通过顶点 B 和 V 以获得 Z。我希望能够将该序列中的每个顶点存储到一个数组中。然后将该数组放入一个更大的数组列表中,该列表将包含所有序列。问题是我不确定将它放在哪里,因为下面的 while 循环用于更新边的成本。
from queue import PriorityQueue
class Graph:
def __init__(self, num_of_vertices):
self.v = num_of_vertices
self.edges = [[-1 for i in range(num_of_vertices)] for j in range(num_of_vertices)]
self.visited = []
def add_edge(self, u, v, weight):
self.edges[u][v] = weight
self.edges[v][u] = weight
def dijkstra(self, start_vertex):
D = {v:float('inf') for v in range(self.v)}
V = {v:None for v in range(self.v)}
D[start_vertex] = 0
pq = PriorityQueue()
pq.put((0, start_vertex))
AllPathsList = []
while not pq.empty():
(dist, current_vertex) = pq.get()
self.visited.append(current_vertex)
for neighbor in range(self.v):
if self.edges[current_vertex][neighbor] != -1:
distance = self.edges[current_vertex][neighbor]
if neighbor not in self.visited:
old_cost = D[neighbor]
new_cost = D[current_vertex] + distance
if new_cost < old_cost:
pq.put((new_cost, neighbor))
D[neighbor] = new_cost
V[neighbor] = current_vertex
S = []
u = current_vertex
while V[u] != None:
S.insert(0, u)
u = V[u]
S.insert(0, start_vertex)
AllPathsList.append(S)
return D, AllPathsList
def main():
g = Graph(6)
g.add_edge(0, 1, 4)
g.add_edge(0, 2, 7)
g.add_edge(1, 2, 11)
g.add_edge(1, 3, 20)
g.add_edge(3, 4, 5)
g.add_edge(3, 5, 6)
g.add_edge(2, 3, 3)
g.add_edge(2, 4 ,2)
D, AllPathsList = g.dijkstra(0)
for vertex in range(len(D)):
print("Distance from vertex 0 to vertex", vertex, "is:", D[vertex])
print("Particular path is:", AllPathsList[vertex])
main()
通常的过程是跟踪每个顶点的前驱。每次更新顶点的成本时,都会将从那里获得的顶点存储为它的前身。
完成后,您可以沿着前驱链从任何顶点回到源,找到到它的最短路径。
我把它编码出来以更新边的所有成本等,以完成 Dijkstra 的主要目标,即找到从源顶点到所有其他顶点的最短路径。
但我需要帮助的是找出一种方法,将每条最短路径包含的顶点存储到一个数组中,该数组包含它经过的每条路径的顶点。
例如,假设从源顶点 (A) 到顶点 (Z) 的最短路径是 A -> B -> V -> Z。最短路径通过顶点 B 和 V 以获得 Z。我希望能够将该序列中的每个顶点存储到一个数组中。然后将该数组放入一个更大的数组列表中,该列表将包含所有序列。问题是我不确定将它放在哪里,因为下面的 while 循环用于更新边的成本。
from queue import PriorityQueue
class Graph:
def __init__(self, num_of_vertices):
self.v = num_of_vertices
self.edges = [[-1 for i in range(num_of_vertices)] for j in range(num_of_vertices)]
self.visited = []
def add_edge(self, u, v, weight):
self.edges[u][v] = weight
self.edges[v][u] = weight
def dijkstra(self, start_vertex):
D = {v:float('inf') for v in range(self.v)}
V = {v:None for v in range(self.v)}
D[start_vertex] = 0
pq = PriorityQueue()
pq.put((0, start_vertex))
AllPathsList = []
while not pq.empty():
(dist, current_vertex) = pq.get()
self.visited.append(current_vertex)
for neighbor in range(self.v):
if self.edges[current_vertex][neighbor] != -1:
distance = self.edges[current_vertex][neighbor]
if neighbor not in self.visited:
old_cost = D[neighbor]
new_cost = D[current_vertex] + distance
if new_cost < old_cost:
pq.put((new_cost, neighbor))
D[neighbor] = new_cost
V[neighbor] = current_vertex
S = []
u = current_vertex
while V[u] != None:
S.insert(0, u)
u = V[u]
S.insert(0, start_vertex)
AllPathsList.append(S)
return D, AllPathsList
def main():
g = Graph(6)
g.add_edge(0, 1, 4)
g.add_edge(0, 2, 7)
g.add_edge(1, 2, 11)
g.add_edge(1, 3, 20)
g.add_edge(3, 4, 5)
g.add_edge(3, 5, 6)
g.add_edge(2, 3, 3)
g.add_edge(2, 4 ,2)
D, AllPathsList = g.dijkstra(0)
for vertex in range(len(D)):
print("Distance from vertex 0 to vertex", vertex, "is:", D[vertex])
print("Particular path is:", AllPathsList[vertex])
main()
通常的过程是跟踪每个顶点的前驱。每次更新顶点的成本时,都会将从那里获得的顶点存储为它的前身。
完成后,您可以沿着前驱链从任何顶点回到源,找到到它的最短路径。