Skip to content

Commit 3b92778

Browse files
committed
Add script which finds MST of a given undirected graph
I am planning to employ Kruskal's algorithm, right now the code i have written just serves to store and setup a graph in the form of adjencency list. Signed-off-by: Aditya Prasad <[email protected]>
1 parent f5f6859 commit 3b92778

File tree

1 file changed

+189
-0
lines changed

1 file changed

+189
-0
lines changed

Kruskal's.py

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
# Implementation of Kruskal's Algorithm
2+
3+
# this is a greedy algorithm to find a MST (Minimum Spanning Tree) of a given connected, undirected graph. graph
4+
5+
# So I am implementing the graph using adjacency list, as the user wont be
6+
# entering too many nodes and edges.The adjacency matrix is a good implementation
7+
# for a graph when the number of edges is large.So i wont be using that here
8+
9+
# Vertex, which will represent each vertex in the graph.Each Vertex uses a dictionary
10+
# to keep track of the vertices to which it is connected, and the weight of each edge.
11+
class Vertex:
12+
13+
# Initialze a object of this class
14+
# we use double underscore
15+
def __init__(self, key):
16+
# we identify the vertex with its key
17+
self.id = key
18+
# this stores the info about the various connections any object
19+
# (vertex) of this class has using a dictionary which is called connectedTo.
20+
# initially its not connected to any other node so,
21+
self.connectedTo={}
22+
23+
# Add the information about connection between vertexes into the dictionary connectedTo
24+
def addNeighbor(self,neighbor,weight=0):
25+
# neighbor is another vertex we update the connectedTo dictionary ( Vertex:weight )
26+
# with the information of this new Edge, the key is the vertex and
27+
# the edge's weight is its value. This is the new element in the dictionary
28+
self.connectedTo[neighbor] = weight
29+
30+
# Return a string containing a nicely printable representation of an object.
31+
def __str__(self):
32+
return str(self.id) + ' connectedTo: ' + str([x.id for x in self.connectedTo])
33+
34+
# Return the vertex's self is connected to in a List
35+
def getConnections(self):
36+
return self.connectedTo.keys()
37+
38+
# Return the id with which we identify the vertex, its name you could say
39+
def getId(self):
40+
return self.id
41+
42+
# Return the value (weight) of the edge (or arc) between self and nbr (two vertices)
43+
def getWeight(self,nbr):
44+
return self.connectedTo[nbr]
45+
46+
# The Graph class contains a dictionary that maps vertex keys to vertex objects (vertlist) and a count of the number of vertices in the graph
47+
class Graph:
48+
49+
def __init__(self):
50+
self.vertList = {}
51+
self.numVertices = 0
52+
53+
54+
# Returns a vertex which was added to the graph with given key
55+
def addVertex(self,key):
56+
self.numVertices = self.numVertices + 1
57+
# create a vertex object
58+
newVertex = Vertex(key)
59+
# set its key
60+
self.vertList[key] = newVertex
61+
return newVertex
62+
63+
# Return the vertex object corresponding to the key - n
64+
def getVertex(self,n):
65+
if n in self.vertList:
66+
return self.vertList[n]
67+
else:
68+
return None
69+
70+
# Returns boolean - checks if graph contains a vertex with key n
71+
def __contains__(self,n):
72+
return n in self.vertList
73+
74+
# Add's an edge to the graph using addNeighbor method of Vertex
75+
def addEdge(self,f,t,cost=0):
76+
# check if the 2 vertices involved in this edge exists inside
77+
# the graph if not they are added to the graph
78+
# nv is the Vertex object which is part of the graph
79+
# and has key of 'f' and 't' respectively, cost is the edge weight
80+
if f not in self.vertList:
81+
nv = self.addVertex(f)
82+
if t not in self.vertList:
83+
nv = self.addVertex(t)
84+
# self.vertList[f] gets the vertex with f as key, we call this Vertex
85+
# object's addNeighbor with both the weight and self.vertList[t] (the vertice with t as key)
86+
self.vertList[f].addNeighbor(self.vertList[t], cost)
87+
88+
# Return the list of all key's corresponding to the vertex's in the graph
89+
def getVertices(self):
90+
return self.vertList.keys()
91+
92+
# Returns an iterator object, which contains all the Vertex's
93+
def __iter__(self):
94+
return iter(self.vertList.values())
95+
96+
97+
98+
# Now lets make the graph
99+
the_graph=Graph()
100+
101+
print "enter the number of nodes in the graph"
102+
no_nodes=int(raw_input())
103+
104+
# setup the nodes
105+
for i in range(no_nodes):
106+
print "enter the Node no:"+str(i+1)+"'s key"
107+
the_graph.addVertex(raw_input())
108+
109+
print "enter the number of edges in the graph"
110+
no_edges=int(raw_input())
111+
112+
113+
# setup the edges
114+
for i in range(no_edges):
115+
print "For the Edge no:"+str(i+1)
116+
print "of the 2 nodes involved in this edge \nenter the first Node's key"
117+
node1_key=raw_input()
118+
print "\nenter the second Node's key"
119+
node2_key=raw_input()
120+
print "\nenter the cost (or weight) of this edge (or arc) - an integer"
121+
cost=int(raw_input())
122+
# add the edge with this info
123+
the_graph.addEdge(node1_key,node2_key,cost)
124+
the_graph.addEdge(node2_key,node1_key,cost)
125+
126+
print "enter the maximum weight possible for any of edges in the graph"
127+
max_weight=int(raw_input())
128+
129+
# graph DONE - start MST finding
130+
131+
# step 1 : Take all edges and sort them
132+
133+
# Time Complexity of Solution:
134+
# Best Case O(n+k); Average Case O(n+k); Worst Case O(n+k),
135+
# where n is the size of the input array and k means the
136+
# values(weights) range from 0 to k.
137+
def counting_sort(weights,max_weight):
138+
# these k+1 counters are made here is used to know how many times each value in range(k+1) (0 to k) repeats
139+
counter=[0]*(k+1)
140+
for i in weights:
141+
# if you encounter a particular number increment its respective counter
142+
counter[i] += 1
143+
# no idea why ndx?! it is the key for the output array
144+
ndx=0
145+
# traverse though the counter list
146+
for i in range(len(counter)):
147+
# if the count of i is more than 0, then append that many 'i'
148+
while 0<counter[i]:
149+
# rewrite the array which was given to make it ordered
150+
weights[ndx] = i
151+
ndx += 1
152+
# reset the counter back to the set of zero's
153+
counter[i] -= 1
154+
155+
# now we have a optimal sorting function in hand, lets sort the list of edges.
156+
# a dictionary with weights of an edge and the vertexes involved in that edge.
157+
vrwght={}
158+
for ver1 in the_graph:
159+
print "ver1 = "
160+
print ver1
161+
for ver2 in ver1.getConnections():
162+
vrwght[ver1.connectedTo[ver2]]=[ver1.getId(),ver2.getId()]
163+
164+
print vrwght
165+
print vrwght.keys()
166+
print the_graph.getVertices()
167+
print the_graph.getVertices()
168+
169+
170+
171+
172+
173+
174+
175+
176+
177+
178+
179+
180+
181+
182+
183+
184+
185+
186+
187+
188+
189+

0 commit comments

Comments
 (0)