https://bradfieldcs.com/algos/graphs/dijkstras-algorithm/
我不太明白为什么这是真的。他们声称,通过检查current_distance > distances[current_vertex]
,我们可以准确地处理每个节点一次。但是,这对我来说并不正确,因为while循环的最后两行是
distances[neighbor] = distance
heapq.heappush(pq, (distance, neighbor))
因此,我认为每次将节点推入堆时,如果再次将其弹出,并且我们观察到current_vertex, current_vertex
(弹出的节点和权重),则distance [neighbor]将等于current_distance。因此,该节点将得到重新处理,并且不会像以前声明的那样被跳过。
import heapq
def calculate_distances(graph, starting_vertex):
distances = {vertex: float('infinity') for vertex in graph}
distances[starting_vertex] = 0
pq = [(0, starting_vertex)]
while len(pq) > 0:
current_distance, current_vertex = heapq.heappop(pq)
# Nodes can get added to the priority queue multiple times. We only
# process a vertex the first time we remove it from the priority queue.
if current_distance > distances[current_vertex]:
continue
for neighbor, weight in graph[current_vertex].items():
distance = current_distance + weight
# Only consider this new path if it's better than any path we've
# already found.
if distance < distances[neighbor]:
distances[neighbor] = distance
heapq.heappush(pq, (distance, neighbor))
return distances
有人可以告诉我我在这里想念的吗?我知道每个节点只应处理一次,但我不明白为什么该代码如此处理。而且我看不到哪里错了。
答案 0 :(得分:1)
可以将顶点多次添加到堆中。每次将其添加到具有不同距离的堆中。现在,您终于可以处理它了。由于它是优先级队列,因此您将处理一对(vertex, distance)
,且距离最短。
两个想法:
首先,到顶点的距离总是减小。这意味着对于给定的顶点,只有一个(vertex, distance)
可以被触发:即距离最小的一个(除非稍后到达距离更小的一对)。换句话说,当顶点被处理时,堆中的所有其他对将不会被处理。
顶点处理后,其距离无法更改。原因是Dijkstra选择了距离最小的顶点。并且由于所有边缘权重均为正,并且所有其他顶点具有更大的距离,因此到处理的顶点的距离不会减小。因此,顶点对不会出现在堆中。