|
| 1 | +# Copyright (C) Deepali Srivastava - All Rights Reserved |
| 2 | +# This code is part of DSA course available on CourseGalaxy.com |
| 3 | + |
| 4 | +class Vertex: |
| 5 | + def __init__(self, name): |
| 6 | + self.name = name |
| 7 | + |
| 8 | + |
| 9 | +class UndirectedWeightedGraph: |
| 10 | + |
| 11 | + def __init__(self,size=20): |
| 12 | + self._adj = [ [0 for column in range(size)] for row in range(size) ] |
| 13 | + self._n = 0 |
| 14 | + self._vertexList = [] |
| 15 | + |
| 16 | + |
| 17 | + def display(self): |
| 18 | + for i in range(self._n): |
| 19 | + for j in range(self._n): |
| 20 | + print( self._adj[i][j], end =' ') |
| 21 | + print() |
| 22 | + |
| 23 | + |
| 24 | + def numVertices(self): |
| 25 | + return self._n |
| 26 | + |
| 27 | + |
| 28 | + def numEdges(self): |
| 29 | + e = 0 |
| 30 | + for i in range(self._n): |
| 31 | + for j in range(i): |
| 32 | + if self._adj[i][j]!=0: |
| 33 | + e+=1 |
| 34 | + return e |
| 35 | + |
| 36 | + |
| 37 | + def vertices(self): |
| 38 | + return [vertex.name for vertex in self._vertexList] |
| 39 | + |
| 40 | + |
| 41 | + def edges(self): |
| 42 | + edges = [] |
| 43 | + for i in range(self._n): |
| 44 | + for j in range(i): |
| 45 | + if self._adj[i][j] != 0: |
| 46 | + edges.append( (self._vertexList[i].name, self._vertexList[j].name, self._adj[i][j]) ) |
| 47 | + return edges |
| 48 | + |
| 49 | + |
| 50 | + def _getIndex(self,s): |
| 51 | + index = 0 |
| 52 | + for name in (vertex.name for vertex in self._vertexList): |
| 53 | + if s == name: |
| 54 | + return index |
| 55 | + index += 1 |
| 56 | + return None |
| 57 | + |
| 58 | + |
| 59 | + def insertVertex(self,name): |
| 60 | + if name in (vertex.name for vertex in self._vertexList): ######## |
| 61 | + print("Vertex with this name already present in the graph") |
| 62 | + return |
| 63 | + self._vertexList.append( Vertex(name) ) |
| 64 | + self._n += 1 |
| 65 | + |
| 66 | + |
| 67 | + def removeVertex(self,name): |
| 68 | + u = self._getIndex(name) |
| 69 | + if u is None: |
| 70 | + print("Vertex not present in the graph") |
| 71 | + return |
| 72 | + |
| 73 | + self._adj.pop(u) |
| 74 | + |
| 75 | + for i in range(self._n): |
| 76 | + self._adj[i].pop(u) |
| 77 | + |
| 78 | + self._vertexList.pop(u) |
| 79 | + self._n -= 1 |
| 80 | + |
| 81 | + |
| 82 | + def insertEdge(self, s1, s2, w): |
| 83 | + u = self._getIndex(s1) |
| 84 | + v = self._getIndex(s2) |
| 85 | + if u is None: |
| 86 | + print("First vertex not present in the graph") |
| 87 | + elif v is None: |
| 88 | + print("Second vertex not present in the graph") |
| 89 | + elif u == v: |
| 90 | + print("Not a valid edge") |
| 91 | + elif self._adj[u][v] != 0 : |
| 92 | + print("Edge already present in the graph") |
| 93 | + else: |
| 94 | + self._adj[u][v] = w |
| 95 | + self._adj[v][u] = w |
| 96 | + |
| 97 | + |
| 98 | + def removeEdge(self, s1,s2): |
| 99 | + u = self._getIndex(s1) |
| 100 | + v = self._getIndex(s2) |
| 101 | + if u is None: |
| 102 | + print("First vertex not present in the graph") |
| 103 | + elif v is None: |
| 104 | + print("Second vertex not present in the graph") |
| 105 | + elif self._adj[u][v] == 0: |
| 106 | + print("Edge not present in the graph") |
| 107 | + else: |
| 108 | + self._adj[u][v] = 0 |
| 109 | + self._adj[v][u] = 0 |
| 110 | + |
| 111 | + |
| 112 | + def isAdjacent(self, s1, s2): |
| 113 | + u = self._getIndex(s1) |
| 114 | + v = self._getIndex(s2) |
| 115 | + if u is None: |
| 116 | + print("First vertex not present in the graph") |
| 117 | + return False |
| 118 | + elif v is None: |
| 119 | + print("Second vertex not present in the graph") |
| 120 | + return False |
| 121 | + return False if self._adj[u][v] == 0 else True |
| 122 | + |
| 123 | + |
| 124 | + def degree(self,s): |
| 125 | + u = self._getIndex(s) |
| 126 | + if u is None: |
| 127 | + print("Vertex not present in the graph") |
| 128 | + return |
| 129 | + |
| 130 | + deg = 0 |
| 131 | + for v in range(self._n): |
| 132 | + if self._adj[u][v] != 0 : |
| 133 | + deg += 1 |
| 134 | + return deg |
| 135 | + |
| 136 | + |
| 137 | + def kruskals(self): |
| 138 | + edgesList = [] |
| 139 | + |
| 140 | + for u in range(self._n): |
| 141 | + for v in range(self._n): |
| 142 | + if self._adj[u][v] != 0: |
| 143 | + edgesList.append( (u,v,self._adj[u][v]) ) |
| 144 | + |
| 145 | + |
| 146 | + edgesList = sorted(edgesList, key = lambda item: item[2], reverse = True) |
| 147 | + |
| 148 | + for v in range(self._n): |
| 149 | + self._vertexList[v].father = None |
| 150 | + |
| 151 | + r1 = None |
| 152 | + r2 = None |
| 153 | + edgesInTree = 0 |
| 154 | + wtTree = 0 |
| 155 | + |
| 156 | + while len(edgesList)!=0 and edgesInTree < self._n-1 : |
| 157 | + edge = edgesList.pop() |
| 158 | + v1 = edge[0] |
| 159 | + v2 = edge[1] |
| 160 | + |
| 161 | + v = v1 |
| 162 | + while self._vertexList[v].father != None : |
| 163 | + v = self._vertexList[v].father |
| 164 | + r1 = v |
| 165 | + |
| 166 | + v = v2 |
| 167 | + while self._vertexList[v].father!=None : |
| 168 | + v = self._vertexList[v].father |
| 169 | + r2 = v |
| 170 | + |
| 171 | + if r1 != r2 : #Edge (v1,v2) is included |
| 172 | + edgesInTree += 1 |
| 173 | + print(self._vertexList[v1].name , "->" , self._vertexList[v2].name ) |
| 174 | + wtTree += edge[2] |
| 175 | + self._vertexList[r2].father = r1 |
| 176 | + |
| 177 | + if edgesInTree < self._n-1: |
| 178 | + print("Graph is not connected, no spanning tree possible") |
| 179 | + return |
| 180 | + |
| 181 | + print("Weight of Minimum Spanning Tree is " , wtTree) |
| 182 | + |
| 183 | + |
| 184 | + |
| 185 | +if __name__ == '__main__': |
| 186 | + |
| 187 | + g = UndirectedWeightedGraph() |
| 188 | + |
| 189 | + g.insertVertex("Zero") |
| 190 | + g.insertVertex("One") |
| 191 | + g.insertVertex("Two") |
| 192 | + g.insertVertex("Three") |
| 193 | + g.insertVertex("Four") |
| 194 | + g.insertVertex("Five") |
| 195 | + g.insertVertex("Six") |
| 196 | + g.insertVertex("Seven") |
| 197 | + g.insertVertex("Eight") |
| 198 | + g.insertVertex("Nine") |
| 199 | + |
| 200 | + g.insertEdge("Zero", "One", 19) |
| 201 | + g.insertEdge("Zero", "Three", 14) |
| 202 | + g.insertEdge("Zero", "Four", 12) |
| 203 | + g.insertEdge("One", "Two", 20) |
| 204 | + g.insertEdge("One", "Four", 18) |
| 205 | + g.insertEdge("Two", "Four", 17) |
| 206 | + g.insertEdge("Two", "Five", 15) |
| 207 | + g.insertEdge("Two", "Nine", 29) |
| 208 | + g.insertEdge("Three", "Four", 13) |
| 209 | + g.insertEdge("Three", "Six", 28) |
| 210 | + g.insertEdge("Four", "Five", 16) |
| 211 | + g.insertEdge("Four", "Six", 21) |
| 212 | + g.insertEdge("Four", "Seven", 22) |
| 213 | + g.insertEdge("Four", "Eight", 24) |
| 214 | + g.insertEdge("Five", "Eight", 26) |
| 215 | + g.insertEdge("Five", "Nine", 27) |
| 216 | + g.insertEdge("Six", "Seven", 23) |
| 217 | + g.insertEdge("Seven", "Eight", 30) |
| 218 | + g.insertEdge("Eight", "Nine", 35) |
| 219 | + |
| 220 | + g.kruskals() |
0 commit comments