Babu lives in a certain village A, and having been in the same village all his life, he longs to travel to the villages reachable from his. Due to time and work constraint, he can only get to one village at a time, and he has therefore to plan accordingly. His idea is to sort the distances from his village to each of the other villages in increasing order, and to visit the villages in that order. So his first task is to get the shortest distances from A to every other village.
A map of Babu's village and all the other villages is as shown below. As can be seen, Babu, the guy drawn as a red stick figure, is currently at his own village, village A. There are roads interconnecting some of the villages, and you can see the length of the roads in the drawing.
Assume that Babu at this point doesn't know yet what's the actual shortest distance from A to every other village. He knows of course that the distance from A to A is 0, and mark it down as shown in the map below. And he puts the distance to every other village as infinity. He will update the value as he goes along.
Now, Babu thinks about all the cities that can be directly reached from A. That's B, G and F, circled as shown in the picture below:
He notes the distances from A to B, G and F, and he list down the places in his notebook - his next-to-visit list -, sorted by distance:
To keep things manageable and his head clear , he keeps as well a logbook containing the list of villages, and for each whether it has been visited, the current shortest distance to it, and the preceding village to route through to reach the destination village.
G, being the nearest - at a distance of 4 from A - , he goes there.
There, he notes the yet-to-visit cities that can be reached directly from G - B, C, D, E, F. He notes down the distances to the cities via G, marking it on the map, overriding the previous values of infinities.
He updates his logbook as well:
He places B, C, D, E, F in his next-to-be-visited list, maintaining the sorted order in the list, and he goes home. The new list is as shown below, with B in the lead, it being the nearest next to visit.
So next he visited B, and he mark on the map the next villages to be visited. From B, there's only one directly reachable village that's yet to be visited - C. But the distance to C via B is 9, not less than that distance already recorded for C, so no change in the logbook. The preceding village for C remains as G. And C is already in the next-to-visit list; so no change whatsoever.
With B, now out from the next-to-visit list, we now have as follows:
So Babu goes to D next.
From D, the villages directly reachable are C and E. However, distance to C through D would be 6+9 = 15, greater than the 9 already recorded. And E through D would be 6 + 5 = 11, way more than the 7 recorded. So the distances to C ad E should not change in Babu's logbook.
Next trip for Babu will be to E, as indicated in his next-to-visit list:
So he goes to E, and from E, he notes that the next to visit village is F. But the distance to F through E is 11, more than the recorded distance for F. So nothing much to do here.
By this point, Babu's logbook looks as follows:
Only F and C left.
Finishing it all off, eventually Babu's logbook looks as follows:
The distances shown in the logbook now will be the final distances, the shortest distance from village A to every other village.
The algorithmic approach adopted by Babu is referred to these days as Dijkstra's Algorithm. In Python, we can have it implemented as shown below. I used the heap data structure in the code, to maintain a sorted list of unvisited nodes. Heap and Heapsort will be in a different post/
# the starting node
def dijkstra(adjmat, unvisited_queue, start):
# in adjmat, -1 entry at (i,j) indicates there is no edge between node i and j
start['dist'] = 0
heapq = Heap('dist')
# Put all nodes into the heap; the heap will maintain a sorted list
heapq.InsertAll(unvisited_queue)
# Repeat until the heap is empty
while heapq.Size() > 0:
# Pops the node with the smallest distance
current = heapq.Pop()
# Get the index for that node
currIndex = current['index']
# Get the visit status for the node to True
current['visited'] = True
# Get list of nodes adjacent from the current node
adjacent = [unvisited_queue[i] for i in range(len(unvisited_queue))
if unvisited_queue[i]['index'] != currIndex and
adjmat[unvisited_queue[i]['index']][currIndex] >= 0]
# Repeat for each adjacent node
for next in adjacent:
# if the adjacent node has already been visited, skip
if next['visited'] == True:
continue
# get the index for the adjacent node
nextIndex = next['index']
# compute distance to adjacent node via current node
new_dist = current['dist'] + adjmat[currIndex][nextIndex]
# if new distance is less, update the one stored in the adj node
if new_dist < next['dist']:
next['dist'] = new_dist
# the current node now precedes the adj node
next['preceding'] = currIndex
# we have to make sure that the information is updated in the heap
heapq.Change(next)
return nodes
.jpg)


