5 Ways to Find the Shortest Path in a Graph
By: Johannes Baum
Tags: JavaScript, Programming, Technical Interviews, Algorithms, Coding Interviews

4. Dijkstra’s Algorithm

This algorithm might be the most famous one for finding the shortest path. Its advantage over a DFS, BFS, and bidirectional search is that you can use it in all graphs with positive edge weights. Don’t try it on graphs that contain negative edge weights because termination is not guaranteed in this case.

Crash Course: Priority Queues

To understand Dijkstra’s algorithm, it is essential to understand priority queues. A priority queue is an abstract data structure that allows the following operations:

isEmpty : checks if the priority queue contains any elements

: checks if the priority queue contains any elements insert : inserts an element along with a priority value

: inserts an element along with a priority value extractHighestPriority : returns the element with the highest priority and removes it from the priority queue

What does priority mean? Mathematically, the priority must allow a partial order to be defined on the elements of the priority queue. In most cases, it is a simple integer p and the element with the highest priority is the element with the smallest (or largest) value for p. In our case, we need the priority queue to store all nodes in the graph along with their distance to our start node. So our extractHighestPriority operation will be called extractMin , which is a more descriptive name for retrieving a node with the minimum distance to the start node.

How does Dijkstra’s algorithm work?

Before we look at the code, let me shortly describe the algorithm so that you get an idea of how it works.

We start by initializing the shortest path from our start node to every other node in our graph. Initially, this will be infinity for every node other than the start node itself. The start node will be initialized with 0 because that is the distance to itself. We insert all nodes to our priority queue along with their previously initialized distance to our start node as a priority.

Now begins the actual work. Until the priority queue is not empty, we extract the node with the current shortest known distance to our start node. Let’s call it currentNode . Then we loop over all neighbors of currentNode , and for each one, we check if reaching it through currentNode is shorter than the currently known shortest path to that neighbor. If so, we update the shortest distance to the neighbor and proceed. But see for yourself:

We gave a callback function to the priority queue that has access to our distances map. This is used in the priority queue implementation to get the minimum distance. However, the implementation of the priority queue should not be discussed in this piece.

Performance

The time complexity of this algorithm highly depends on the implementation of the priority queue. Let n be the number of nodes and e be the number of edges in the graph. If it is implemented by a simple array, Dijkstra’s algorithm will run in O(n²). However, the more common implementation uses a Fibonacci heap as the priority queue. In this case, the runtime is within O(e + n log(n)).