@@ -136,7 +136,7 @@ def __iter__(self):
136
136
# values(weights) range from 0 to k.
137
137
def counting_sort (weights ,max_weight ):
138
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 )
139
+ counter = [0 ]* (max_weight + 1 )
140
140
for i in weights :
141
141
# if you encounter a particular number increment its respective counter
142
142
counter [i ] += 1
@@ -155,25 +155,137 @@ def counting_sort(weights,max_weight):
155
155
# now we have a optimal sorting function in hand, lets sort the list of edges.
156
156
# a dictionary with weights of an edge and the vertexes involved in that edge.
157
157
vrwght = {}
158
+ # take every vertex in the graph
158
159
for ver1 in the_graph :
159
- print "ver1 = "
160
- print ver1
160
+ # take every vertex ver1 is connected to = ver2
161
161
for ver2 in ver1 .getConnections ():
162
+ # make the dictionary with the weights and the 2 vertex's involved with the edge (thier key)
162
163
vrwght [ver1 .connectedTo [ver2 ]]= [ver1 .getId (),ver2 .getId ()]
163
164
165
+ print "\n The edges with thier unsorted weights are"
164
166
print vrwght
165
- print vrwght .keys ()
166
- print the_graph .getVertices ()
167
- print the_graph .getVertices ()
168
167
168
+ temp_weights = vrwght .keys ()
169
+ counting_sort (temp_weights ,max_weight )
170
+
171
+ sorted_weights = {}
172
+ for weight in temp_weights :
173
+ sorted_weights [weight ]= vrwght [weight ]
174
+
175
+ print "\n After sorting"
176
+ print sorted_weights
177
+
178
+
179
+ # Now step 2 : now we the smallest edge wrt to weight and add it to the MST,
180
+ # IF the two nodes associated with the edge belong TO DIFFERENT sets.
181
+ # What? well see kruskal's algo for finding the MST is simple,
182
+ # we take the graph, remove all the edges and order them based on thier weight
183
+ # now we replace all the removed edges back to the "graph" (which we just now plucked clean)
184
+ # smallest first. Subject to the condition that adding a edge doesnt cause a CYCLE or LOOP
185
+ # to develop, a tree cant have such loops we must avoid them.so we skip them
186
+ # so this series of steps explains Kruskal's algorithm:
187
+ """
188
+ 1. Take all edges in an array and Sort that array (in an ascending order)
189
+ 2. Take the next (minimum edge), examine its end nodes:
190
+ a) If they belong to different sets, merge their sets and add that edge to the tree
191
+ b) Otherwise skip the edge
192
+ 3. Print the tree obtained.
193
+ """
194
+
195
+ # 2. a) is the method used to check if adding a particular edge will cause a cycle,
196
+ # Thus comes the UNION-FIND algorithm :
197
+ # Many thanks to David Eppstein of the University of California,
198
+ # this is taken from PADS, a library of Python Algorithms and Data Structures
199
+ class UnionFind :
200
+ """Union-find data structure.
201
+
202
+ Each unionFind instance X maintains a family of disjoint sets of
203
+ hashable objects, supporting the following two methods:
204
+
205
+ FIND
206
+ - X[item] returns a name for the set containing the given item.
207
+ Each set is named by an arbitrarily-chosen one of its members; as
208
+ long as the set remains unchanged it will keep the same name. If
209
+ the item is not yet part of a set in X, a new singleton set is
210
+ created for it.
211
+
212
+ UNION
213
+ - X.union(item1, item2, ...) merges the sets containing each item
214
+ into a single larger set. If any item is not yet part of a set
215
+ in X, it is added to X as one of the members of the merged set.
216
+ """
169
217
170
-
171
-
218
+ def __init__ (self ):
219
+ """Create a new empty union-find structure."""
220
+ self .weights = {}
221
+ self .parents = {}
222
+
223
+ def __getitem__ (self , object ):
224
+ """Find and return the name of the set containing the object."""
225
+
226
+ # check for previously unknown object
227
+ # if the object is not present in the dictionary make the object itself its own parent and set its weight as 1
228
+ if object not in self .parents :
229
+ self .parents [object ] = object
230
+ self .weights [object ] = 1
231
+ return object
232
+
233
+ # find path of objects leading to the root
234
+ path = [object ]
235
+ root = self .parents [object ]
236
+ while root != path [- 1 ]:
237
+ path .append (root )
238
+ root = self .parents [root ]
239
+
240
+ # compress the path and return
241
+ for ancestor in path :
242
+ self .parents [ancestor ] = root
243
+ return root
244
+
245
+ def __iter__ (self ):
246
+ """Iterate through all items ever found or unioned by this structure."""
247
+ return iter (self .parents )
248
+
249
+ def union (self , * objects ):
250
+ """Find the sets containing the objects and merge them all."""
251
+ roots = [self [x ] for x in objects ]
252
+ heaviest = max ([(self .weights [r ],r ) for r in roots ])[1 ]
253
+ for r in roots :
254
+ if r != heaviest :
255
+ self .weights [heaviest ] += self .weights [r ]
256
+ self .parents [r ] = heaviest
257
+
258
+ MST = {}
259
+ # lets make a union-find instance - this calls init
260
+ X = UnionFind ()
261
+
262
+ # sets up the graph - make singleton sets for each vertex
263
+ for vertex_key in the_graph .getVertices ():
264
+ # get all the vertices set up, make them parents of themselfs, each in thier individual sets
265
+ # execute FIND for all the vertex's in the_graph
266
+ X [the_graph .getVertex (vertex_key )]
267
+
268
+ # now the UNION.
269
+ for weight in sorted_weights :
270
+ # here sorted_weights[weight] gives the set of 2 vertex's involved in the that edge
271
+ if (X [the_graph .getVertex (sorted_weights [weight ][0 ])]== X [the_graph .getVertex (sorted_weights [weight ][1 ])]):
272
+ # if both vertices have the same parent (name) then they are in the same set, so ignore this edge
273
+ pass
274
+ else :
275
+ # else as they belong to different sets we can ADD this edge to the MST (MST will be a subset of sorted_weights)
276
+ MST [weight ]= sorted_weights [weight ]
277
+ # and merge the sets these two vertices belong to thus we call union on them.
278
+ X .union (the_graph .getVertex (sorted_weights [weight ][0 ]),the_graph .getVertex (sorted_weights [weight ][1 ]))
279
+
280
+ # thus we have the MST done
281
+
282
+ print " \n \n In the graph with these vertex's"
283
+ print the_graph .getVertices ()
172
284
285
+ print "\n With these edges between the vertexes given above, we obtain a Minimal Spanning Tree\n "
286
+ print MST
173
287
174
-
175
-
176
-
288
+ print "\n Please note this is a dictionary with key as the weight of the edge and value as the key's of the two vertex's involved in this edge"
177
289
178
290
179
291
0 commit comments