Algorithm 为什么Dijkstra算法会松弛最短路径树中已存在顶点的相邻边?

Algorithm 为什么Dijkstra算法会松弛最短路径树中已存在顶点的相邻边?,algorithm,clrs,Algorithm,Clrs,在第24章第658页CLRS第三版的DIJKSTRA伪代码中,在内部循环中,当从新添加的顶点放松相邻边时,为什么允许放松已从队列中去除并添加到树的最短路径的边 while(Q not empty){ u = extractMin from Q; Add S to the shortest path tree; for each vertex v adjacent to u relax(u,v,w) } 为什么内部循环不检查顶点是否已经是最短路径树的一部分 while(Q not e

在第24章第658页CLRS第三版的DIJKSTRA伪代码中,在内部循环中,当从新添加的顶点放松相邻边时,为什么允许放松已从队列中去除并添加到树的最短路径的边

while(Q not empty){
 u = extractMin from Q;
 Add S to the shortest path tree;
 for each vertex v adjacent to u 
 relax(u,v,w)

}
为什么内部循环不检查顶点是否已经是最短路径树的一部分

while(Q not empty){
     u = extractMin from Q;
     Add S to the shortest path tree;
     for each vertex v adjacent to u 
     if v is in Q 
      then relax(u,v,w)

    }

哪种方法是正确的?

放松的第一件事是检查

if v.d > u.d + w(u,v)
如果
v
已在最短路径树上,则检查将始终失败,
relax
将不会继续。如果v在Q中,
检查将是多余的


然而,在算法的具体实现中,if
if v in Q
比if v.d>u.d+w(u,v)
的运算速度要快得多,包括它可能是一个有用的优化。

relax做的第一件事就是检查

if v.d > u.d + w(u,v)
如果
v
已在最短路径树上,则检查将始终失败,
relax
将不会继续。如果v在Q中,
检查将是多余的


然而,在算法的具体实现中,if
if v in Q
比if v.d>u.d+w(u,v)
的运算速度要快得多,包括它可能是一种有用的优化。

这两种方法在功能上都是正确的。但是,您的版本不如CLRS版本优化。 如果v在Q中,您不想执行
,因为这是一个O(logn)操作,而
如果v.d>u.d+w(u,v)
是O(1)。在算法开始时,Q包含图中的所有顶点。因此,对于一个非常大的稀疏连接图,您的版本最终将比CLR糟糕得多

然而,你的问题并非完全没有道理。在CLRS中对Dijkstra算法的解释有点让人困惑,这正是我来到这个讨论主题的原因。查看第658页上的伪代码:

DIJKSTRA(G, w, s)
1 INITIALIZE-SINGLE-SOURCE(G, s)
2 S = 0
3 Q = G.V
4 while Q not empty
5     u = EXTRACT-MIN(Q)
6     add u to S
7     for each vertex v in G.Adj[u]
8         RELAX(u, v, w)

有人想知道维持S到底有什么意义?如果我们完全通过删除第2行和第6行来删除它,那么算法仍然有效,完成后,您可以按照前面的指针(已存储在每个顶点中)向后通过图形打印最短路径(使用第601页的
print-path(G,s,v)
,如第647页所述)。在这里,S似乎更多地被用作一种解释工具,以说明Dijkstra是一种贪婪算法,但在实际的图形实现中,在我看来,似乎不需要它。

这两种方法在功能上都是正确的。但是,您的版本不如CLRS版本优化。 如果v在Q中,您不想执行
,因为这是一个O(logn)操作,而
如果v.d>u.d+w(u,v)
是O(1)。在算法开始时,Q包含图中的所有顶点。因此,对于一个非常大的稀疏连接图,您的版本最终将比CLR糟糕得多

然而,你的问题并非完全没有道理。在CLRS中对Dijkstra算法的解释有点让人困惑,这正是我来到这个讨论主题的原因。查看第658页上的伪代码:

DIJKSTRA(G, w, s)
1 INITIALIZE-SINGLE-SOURCE(G, s)
2 S = 0
3 Q = G.V
4 while Q not empty
5     u = EXTRACT-MIN(Q)
6     add u to S
7     for each vertex v in G.Adj[u]
8         RELAX(u, v, w)
有人想知道维持S到底有什么意义?如果我们完全通过删除第2行和第6行来删除它,那么算法仍然有效,完成后,您可以按照前面的指针(已存储在每个顶点中)向后通过图形打印最短路径(使用第601页的
print-path(G,s,v)
,如第647页所述)。在这里,S似乎更多地被用作一种解释工具,以说明Dijkstra是一种贪婪算法,但在实际的图形实现中,在我看来,似乎不需要它