On the Wikipedia page for Dijkstra's algorithm, they mark visited nodes so they wouldn't be added to the queue again. However, if a node is visited then there can be no distance to that node that is shorter, so doesn't the check alt < dist[v]
already account for visited nodes? Am I misunderstanding something about the visited set?
for each neighbor v of u:
alt := dist[u] + dist_between(u, v); // accumulate shortest dist from source
if alt < dist[v] && !visited[v]:
dist[v] := alt; // keep the shortest dist from src to v
previous[v] := u;
insert v into Q; // Add unvisited v into the Q to be processed
end if
end for
Dijkstra's algorithm solves the shortest-path problem for any weighted, directed graph with non-negative weights. It can handle graphs consisting of cycles, but negative weights will cause this algorithm to produce incorrect results.
Dijkstra's algorithm in default form computes the shortest distance from a starting node to all connected nodes. Even in this form it does not visit all nodes: only the vertices of a connected component have to be checked.
Dijkstra's Algorithm finds the shortest path between a given node (which is called the "source node") and all other nodes in a graph. This algorithm uses the weights of the edges to find the path that minimizes the total distance (weight) between the source node and all other nodes.
You can return distance between two nodes, distances between a node and all other nodes, distance and a path, distance and a previous node (which is enough to construct a path). So in the case of wikipedia article - it returns you distances to all vertices and what is the previous vertex in the path to get your path.
There are actually 2 sets you need to consider:
The visited set contains those vertices which have been popped from the queued set. These cannot be re-visited because by definition, the shortest path from the start to these vertices has already been discovered
The queued set contains unexplored vertices queued in order of shortest-distance-to the start vertex. This queue is usually represented using a [min] heap structure.
Depending on the density of the graph, each vertex has a possibility of being a part of more than one edge. Note that an edge is the smallest component that connects a vertex to another vertex. Therefore, this implies possibility of having more than one vertex with an edge to the current vertex.
Each iteration of the outer loop of the Dijkstra's algorithm takes the vertex (from the queued set) with the smallest distance to the start vertex, and relaxes the edge cost to each vertex connected to it. If the vertex is already in the queued set, it's value and position in the queue is updated.
The reason alt < dist[v]
is done is because it is possible to encounter a vertex that is already in the queue more than once so each time it is encountered you have to make sure that before you edit it's distance to the source vertex, it's current distance is larger than the new distance you want to assign to it (alt < dist[v]
) and it is not processed as visited (!visited[v]
)
Dijkstra's algorithm by definition provides the guarantee that as soon as a node is marked as visited
, the distance value of that node is the shortest to the source. If a node is marked as visited, this does not imply that the distance to the source from that node is the shortest distance in comparison to the distance from the source to any other node. Visited implies that the objective of Dijkstra's algorithm has been met for that node; i.e. it currently stores the smallest distance from the source to itself.
If you completely want to discard checking for visited, then what you can do is that once you mark a node as visited, you iterate through all the edges connected to that node and delete them. This makes sure that any future nodes processed, does not have an edge that connects to any node marked as visited. However, because the graph is represented using an adjacency list, going with this option will be costly in terms of time; And depending on how dense the graph is, you would have been better off just having a visited set.
If you represent your graph using an adjacency matrix, then the benefit of this is that the check will only cost O(N)
time. However, adjacency matrix uses N2 space vs N space of adjacency list, you will be paying the price for this in memory, which may or may not be so bad depending on the graph size.
Once you understand all this, you will come to see that everything done in the code is needed to produce the correct results.
Yes, you're right. There's no need for the visited vector.
If a node is visited then there cannot exist a distance to that node that is shorter, so, as you said, checking alt < dist[v]
is enough.
Take a look here:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With