1

In the DIJKSTRA pseudo-code in chapter 24 page 658 CLRS Third Edition, in the inner loop, while relaxing adjacent edges from the new added vertex why is the relaxing allowed on the edges already dequed from the queue and added to Shortest Path to tree?

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)

}

Why is the inner loop not checking if the vertex is already part of Shortest path tree like,

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)

    }

Which is correct approach?

Sohail Khan
  • 279
  • 1
  • 3
  • 10

2 Answers2

2

The first thing relax does is to check

if v.d > u.d + w(u,v)

If v is already on the shortest path tree, the check will always fail and relax will not proceed. An if v is in Q check would be redundant.

However, if if v is in Q is a significantly faster operation than if v.d > u.d + w(u,v) in a concrete implementation of the algorithm, including it may be a useful optimization.

Janne Karila
  • 24,266
  • 6
  • 53
  • 94
2

Both approaches are functionally correct. However, your version is less optimal than the CLRS version. You don't want to do if v is in Q because that's an O(log n) operation, whereas if v.d > u.d + w(u, v) is O(1). At the beginning of the algorithm, Q contains all the vertices in the graph. So for, say a very large sparsely-connected graph, your version would end-up being much worse than CLRS.

Your question, however, is not entirely without merit. The explanation for Dijkstra's algorithm in CLRS is a bit confusing, which is what actually brought me to this discussion thread. Looking at the pseudo-code on page 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)

one wonders what is the point of maintaining S at all? If we do away with it entirely by removing lines 2 and 6, the algorithm still works, and after it's complete you can print the shortest path by following the predecessor pointers (already stored in each vertex) backwards through the graph (using PRINT-PATH(G, s, v) on page 601, as described on page 647). S seems to be used more as an explanation tool here, to illustrate the fact that Dijkstra is a greedy algorithm, but in an actual graph implementation, seems to me it would not be needed.

  • First, apologies for reviving an old question. I'm studying for my Ph.D. QE and spending an inordinate amount of time with the pseudo-code in CLRS too. About "one wonders what is the point of maintaining S at all", I came across [this great discussion in CS StackExchange](https://cs.stackexchange.com/q/102370) that confirms `S` is indeed an explanatory tool and can be removed from the code. – Christian Garbin Feb 19 '22 at 22:48