Dijkstra’s Algorithm

ref – https://www.tutorialspoint.com/Dijkstra-s-algorithm-in-Javascript

Dijkstra’s Algorithm is used for solving single source shortest path problems. In this algorithm, a single node is fixed as a source node and shortest paths from this node to all other nodes in graph is found.

Minimum priority queue is the most commonly used data structure for implementing Dijkstra’s Algorithm because the required operations to be performed in Dijkstra’s Algorithm match with specialty of a minimum priority queue.

Time complexity of Dijkstra’s algorithm is O(N2) because of the use of doubly nested for loops. It depends on how the table is manipulated.

Dijkstra’s Algorithm cannot be applied on graphs having negative weight function because calculation of cost to reach a destination node from the source node becomes complex.

Given nodes: A B C D E F G
and their edges:

“A”, “C”, 100
“A”, “B”, 3
“A”, “D”, 4
“D”, “C”, 3
“D”, “E”, 8
“E”, “F”, 10
“B”, “G”, 9
“E”, “G”, 50

We first draw a node graph diagram of it. Keep in mind that from our adjacency list, if we have arrows pointing to each other from two nodes, it’s undirected. If it’s only from one to the other, then it’s directed. So undirected graphs should have double the # of edges than directed graphs.

In our case, it is a directed graph.

Then we set up the the node/distance/prev chart.
The distance means the shortest distance from the starting node to that node. Right now, we initialize all to infinity.
The prev means the previous node that this node connects to. We maximize as null.

Since our starting node is A, our distance is 0, and prev is A.

node distance prev
A 0 A
B Inf null
C Inf null
D Inf null
E Inf null
F Inf null
G Inf null

We then draw the adjacency graph to keep track of all the neighbors of a specific node presented from edges.
For each edge, it creates a neighbor of a node, and we must diagram this in order to keep track.

Finally, we have a queue to get the minimum distance as shall see later.

Start

In our code, we create an instance of our Dijkstra’s Algorithm.

We have the queue ready, so we first push A onto the queue.
queue – [A]

We start by popping the A off the queue and processing it.
queue – []

We look at the unvisited neighbors of A.
Namely, they are C, B, and D.

Distance from A to C is 100. On our chart, distance of A to C is Infinity. 100 < Infinity, so we replace Infinity with 100. Then we push C onto the queue. queue - [C]

node distance prev
A 0 A
B Inf null
C 100 A

Distance from A to B is 3. On the chart, A to B’s distance is Infinity. Is 3 < Infinity? Yes! so we replace the values in the chart, then push node B onto the queue: queue - [B, C]

node distance prev
A 0 A
B 3 A
C 100 null

Distance from A to D is 4. On the chart A to D’s distance is Infinity. Is 4 < Infinity? Yes! so we replace it on the chart, and push node D onto the queue: queue - [B, D, C]

node distance prev
A 0 A
B 3 A
C 100 A
D 4 A

We’ve processed all of node A’s neighbors. (Linked List) Once that’s done. The queue is a priority minimum queue, so we pop the queue to get the minimum distanced node, which is B.

Queue – [D, C]

B with priority of 3

At B, we process all its unvisited neighbors. In the Adjacency list, B is connected to G. B to G is 9. Distance from starting point A to B is 3.
so 3 + 9 = 12. Is 12 < Infinity? yes, so let's update the table.

node distance prev
A 0 A
B 3 A
C 100 A
D 4 A
G 12 B

Then we push G onto the queue.

Queue – [D, G, C]

Processing D, priority 4

But because D has the minimum distance at 4, we pop it from the queue.

Queue – [G, C]

D has edges to C and E.

Distance from D to C is 3. Distance from start to D 4. Distance from start to C = 3 + 4 = 7. Is 7 < Infinity? Yes, let's update it. Insert C with priority 7 into the queue. Notice we already have priority 100 for C in the queue. We simply replace the value 100 with 7. This is so because we have found a shorter distance than 100.

node distance prev
A 0 A
B 3 A
C 7 D
D 4 A
G 12 B

We then look at neighbor E. From D to E is 8. From start to D is 4. From start to E is 4 + 8 = 12. Is 12 < Infinity ? Yes, update table. Then push E with priority 12 onto the queue.

node distance prev
A 0 A
B 3 A
C 7 D
D 4 A
E 12 D
G 12 B

so we’re finished running through all edges for ‘D’.

Queue – [C(7), E(12), G(12)]

Process C with priority of 7

We pop C because it has minimum prioirty.

Queue – [E(12), G(12)]

C has no edges in our Adjacency list, so we skip.

Process G with priority of 12

Queue – [E(12)]

Then we process G with priority of 12. G has no edges in our Adjacency list, so we skip.

Process E with priority of 12

So we then process node E. It has edges F and G.

E to F is 10. Min distance from from start point A to E is 12.
Is 10+12=22 smaller than what’s on our chart? (Infinity) Yes! So we update the chart.

node distance prev
A 0 A
B 3 A
C 7 D
D 4 A
E 12 D
F 22 E
G 12 B

Then push F onto the queue.

Queue – [F(22)].

Let’s continue and process G.

E to G is 50. Minimum distance from start to E is 12.
Start to G is 50 + 12 = 62. From our Chart, A to G has 12. Is 62 < 12? No! So we don't update the chart. We do not push G onto the queue. We then pop the queue and continue...

Processing F at priority 22

No edges for F. Queue is empty. WE’re now done.

The final answer is:

node distance prev
A 0 A
B 3 A
C 7 D
D 4 A
E 12 D
F 22 E
G 12 B

Where the shortest distance from A to any of the nodes are listed under the distance column.

For example, say I want to know what is the shortest distance from A to G. It is 12 by the way of A, B, G. The 12 shows that A to G takes 12 steps and G’s previous is B. We look at B and its previous is A. So we know that it goes A -> B -> G.

I want to know what is the shortest distance from A to C. Looking at the chart, A to C has min distance of 7, by the way of A, B, C.
C’s previous is B. And B’s previous is A.

Code Explanation

So we have a bunch of dictionaries to represent our chart data. We have everything from distance, prev, and nodes. We have _edges to represent the adjacency list, and _visited to show which ones have been visited.

We set up a minimum priority queue.

And initialize everything first. The start node’s distance is always 0.
We set the other distances to Infinity.
We set the previous nodes to null.
And finally, push the start node onto the queue.

So the basic idea here is that we start the algorithm by dequeueing the starting node.
We continue dequeueing from the priority queue until it is empty.

The point of processing each node as they come in is that we get the minimum priority (distance) first.
Then as we process them, we update the chart. We are done when the queue is empty.

As each node with the minimum priority (distance) comes off the queue, we process their edge list. This can be visually seen by the adjacency list. In our case, it is the _edges dictionary.

So if an edge has not been visited, we process it.
We the get the minimum distance from starting to current node, and then add the distance of the current edge.
If it’s less than what we have in the chart, we update the chart.

This is to say that we found a shorter way. In this case, we push the current node into the queue along with its distance as the priority.
Due to the queue being a minimum priority queue, it will always process the shortest distance nodes.

If it’s not, then this way is longer, and we don’t care for it.

Source Code

Node, Linked List and Minimum Priority Queue

Dijkstra’s Algorithm