This will be a 3 Part series of posts where I will be implementing the Dijkstra's Shortest Path algorithm in Python. The three parts will be
1) Representing the Graph
2) Priority Queue
3) The Algorithm
To represent a graph we'll be using an Adjacency List. Another alternative is using an Adjacency Matrix, but for a sparse graph an Adjacency List is more efficient.
Adjacency List
An Adjacency List is usually represented as a HashTable (or an Array) where an entry at `u` contains a Linked List. The Linked List contains `v` and optionally another parameter `w`. Here `u` and `v` are node(or vertex) labels and `w` is the weight of the edge. By Traversing the linked list we obtain the immediate neighbours of `u`. Visually, it looks like this.
For implementing this in Python, we'll be using the dict() for the main HashTable. For the Linked List we can use a list of 2 sized tuples (v,w).
So here's the python code
Sidenote: Instead of a list of tuples, you can use a dict(), with the key as `v` and value as weight (or a tuple of edge properties). The Advantage being you can check for adjacency faster. In Dijkstra, we don't need that check, so I'll stick with a list for now.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import fileinput | |
# add_edge (u -> v) with weight w to graph g | |
def add_edge(graph,u,v,w): | |
if u in graph: #vertex u already in graph? | |
l = graph[u] #get list of neighbours | |
else: | |
graph[u] = l = list() #insert u into graph and assign an empty list of neighbours | |
l.append((v,w)) #append tuple (v,w) into the neighbour list | |
g = dict() #initialize graph | |
for line in fileinput.input(): | |
u,v,w = map(int,line.split()) | |
add_edge(g,u,v,w) | |
add_edge(g,v,u,w) #undirected graph, edges go both ways | |
print g |
I'll be using the undirected graph from Wikipedia for reference. Here's the graph followed by its textual representation.
(Sorry about the overlapping edge labels, I'm new to Graphviz.)
1 2 7
1 3 9
1 6 14
2 3 10
2 4 15
3 4 11
3 6 2
4 5 6
5 6 9
So what have we accomplished so far? We essentially have stored the entire graph as a data structure, where we can iterate over the neighbours of any vertex using something like
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
for (v,w) in graph[u]: | |
print "%d connected to %d with weight %d" % (u,v,w) |
Comments
Post a Comment