Skip to content

Commit 0627034

Browse files
committed
Add Dijkstra algorithm illustrations and explanations
1 parent e2ed5cc commit 0627034

File tree

1 file changed

+45
-7
lines changed

1 file changed

+45
-7
lines changed

src/algorithms/graph/dijkstra/README.md

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,55 +33,93 @@ and updates the neighbor's distance if smaller. Mark visited
3333

3434
## Step-by-step Dijkstra's algorithm example
3535

36-
Let's say we have a graph of nodes, where each edge has a distance parameter between nodes. Let's say the distance from node `A` and node `B` is `7 meters`, and so on.
36+
Let's say we have a weighted graph of nodes, where each edge has a distance parameter between nodes. Let's say the distance from node `A` and node `B` is `7 meters` (or just `7m` for brevity), and so on.
3737

3838
The algorithm uses [Priority Queue](../../../data-structures/priority-queue/) to always pull the next unvisited vertex that has the smallest distance from the origin node.
3939

40-
The start node by definition has a distance of `0m` from itself. So we start from it, the only node in the priority queue.
40+
The start node, by definition, has a distance of `0m` from itself. So we start from it, the only node in the priority queue.
41+
42+
The rest of the nodes will be added to the priority queue later during the graph traversal (while visiting the neighbors).
4143

4244
![Dijkstra step 1](./images/dijkstra-01.png)
4345

44-
Each neighbor of the pulled (from the queue) node is being traversed to calculate the distance to it from the origin. For example the distance from `A` to `B` is `0 + 7 = 7m`, and so on.
46+
Each neighbor of the pulled (from the queue) node is being traversed to calculate the distance to it from the origin. For example, the distance from `A` to `B` is `0m + 7m = 7m`, and so on.
47+
48+
Every time we visit a not-yet-seen neighbor, we add it to the priority queue, where the priority is the distance to the neighbor node from the origin node.
4549

46-
Every time we visit a not yet seen neighbor, we add it to the priority queue, where the priority is a distance to the neighbor node from the origin node.
50+
The node `B` is being added to the min priority queue to be traversed later.
4751

4852
![Dijkstra step 2](./images/dijkstra-02.png)
4953

54+
Visiting the next neighbor `C` of the node `A`. The distance from the origin node `A` to `C` is `0m + 9m = 9m`.
55+
56+
The node `C` is being added to the min priority queue to be traversed later.
57+
5058
![Dijkstra step 3](./images/dijkstra-03.png)
5159

60+
Same for the node `F`. The current distance to `F` from the origin node `A` is `0m + 14m = 14m`.
61+
62+
The node `F` is being added to the min priority queue to be traversed later.
63+
5264
![Dijkstra step 4](./images/dijkstra-04.png)
5365

54-
Once all the neighbors of the current nodes were checked, the current node is being put to the `visited` set. We don't want to visit such nodes ones again during the upcoming traverses.
66+
Once all the neighbors of the current node were checked, the current node was added to the `visited` set. We don't want to visit such nodes once again during the upcoming traverses.
5567

5668
Now, let's pull out the next node from the priority queue that is closest to the origin (has a shorter distance). We start visiting its neighbors as well.
5769

5870
![Dijkstra step 5](./images/dijkstra-05.png)
5971

60-
If the node that we're visiting (in this case the node `C`) is already in the queue, it means we already calculated the distance to it before but from another node/path (`A → C`). If the current distance to it (from the current neighbor node `A → B → C`) is shorter than the one that was calculated before, we update the distance (in the priority queue) to the shortest one, since we're searching for the shortest paths. If the distance from the current neighbor is actually longer that the once was already calculated, we leave it like this without updating the `C` node distance in the queue.
72+
If the node that we're visiting (in this case, the node `C`) is already in the queue, it means we already calculated the distance to it before, but from another node/path (`A → C`). If the current distance to it (from the current neighbor node `A → B → C`) is shorter than the one that was calculated before, we update the distance (in the priority queue) to the shortest one, since we're searching for the shortest paths. If the distance from the current neighbor is actually longer than the one that was already calculated, we leave it like this without updating the `C` node distance in the queue.
73+
74+
While visiting the node `C` via `B` (the path `A → B → C`), we see that the distance to it would be `7m + 10m = 17m`. This is actually longer than the already recorded distance of `9m` for the path `A → C`. In such cases, we just ignore the longest distance and don't update the priority (the minimum found distance at the moment from the origin node).
6175

6276
![Dijkstra step 6](./images/dijkstra-06.png)
6377

78+
Visiting another neighbor of `B`, which is `D`. The distance to `D` equals `7m + 15m = 22m`. Since we didn't visit `D` yet and it is not in the min priority queue, let's just add it to the queue with a priority (distance) of `22m`.
79+
6480
![Dijkstra step 7](./images/dijkstra-07.png)
6581

82+
At this point, all of the neighbors of `B` were traversed, so we add `B` to the `visited` set. Next, we pull the node that is closest to the origin node from the priority queue.
83+
6684
![Dijkstra step 8](./images/dijkstra-08.png)
6785

86+
Traversing the unvisited neighbors of the node `C`. The distance to node `F` via `C` (the path `A → C → F`) is `9m + 2m = 11m`. This is actually shorter than the previously recorded path `A → F` of `14m` length. In such cases, we update the distance to `F` to `11m` and update its priority in the queue from `14m` to `11m`. We've just found a shorter path to `F`.
87+
6888
![Dijkstra step 9](./images/dijkstra-09.png)
6989

90+
The same goes for `D`. We've just found a shorter path to `D`, where `A → C → D` is shorter than `A → B → D`. Updating the distance from `22m` to `20m`.
91+
7092
![Dijkstra step 10](./images/dijkstra-10.png)
7193

94+
All neighbors of `C` were traversed, so we may add `C` to the `visited` set. Pulling the next closest node from the queue, which is `F`.
95+
7296
![Dijkstra step 11](./images/dijkstra-11.png)
7397

98+
Recording the distance to `E` as `11m + 9m = 20m`.
99+
74100
![Dijkstra step 12](./images/dijkstra-12.png)
75101

102+
Adding the node `F` to the `visited` set, and pulling the next closest node `D` from the queue.
103+
76104
![Dijkstra step 13](./images/dijkstra-13.png)
77105

106+
Distance to `E` via `D` is `20m + 6m = 26m`. This is longer than the already calculated distance to `E` from `F`, which is `20m`. We can discard the longer distance.
107+
78108
![Dijkstra step 14](./images/dijkstra-14.png)
79109

110+
Node `D` is visited now.
111+
80112
![Dijkstra step 15](./images/dijkstra-15.png)
81113

114+
Node `E` is visited now as well. We've finished the graph traversal.
115+
82116
![Dijkstra step 16](./images/dijkstra-16.png)
83117

84-
Now we now the shortest distances to ech node from the start node `A`. In practice, during the distance calculations we also record the the `previousVertices` for each node to be able to show the exact sequence of nodes that forms the shortest path.
118+
Now we know the shortest distances to each node from the start node `A`.
119+
120+
In practice, during the distance calculations, we also record the `previousVertices` for each node to be able to show the exact sequence of nodes that form the shortest path.
121+
122+
For example, the shorter path from `A` to `E` is `A → C → F → E`.
85123

86124
## Implementation example
87125

0 commit comments

Comments
 (0)