-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathkruskal.py
176 lines (121 loc) · 3.79 KB
/
kruskal.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#!/anaconda/bin/python3
class Edge(object):
"""docstring for Edge"""
def __init__(self, start, end, weight):
self.startVertex = start
self.endVertex = end
self.weight = weight
def __lt__(self, otherEdge):
return self.weight < otherEdge.weight
''' By default, __gt__() and __lt__() are each other’s reflection
def __gt__(self, otherEdge):
return self.weight > otherEdge.weight
'''
class DisjointSet(object):
"""docstring for DisjointSet"""
def __init__(self, vertexList):
self._rank = [0 for v in vertexList]
self._parent = [0 for v in vertexList]
self._setCount = 0
self.makeSets(vertexList)
def makeSets(self, vertexList):
for v in vertexList:
self._makeSet(v)
def _makeSet(self, v):
self._parent[v] = v
self._rank[v] = 0
self._setCount += 1
def find(self, v):
if v != self._parent[v]:
self._parent[v] = self.find(self._parent[v])
return self._parent[v]
def union(self, v1, v2):
id1 = self.find(v1)
id2 = self.find(v2)
if id1 == id2:
return # they are in the same set
if self._rank[id1] < self._rank[id2]:
self._parent[id1] = id2
else:
self._parent[id2] = id1
if self._rank[id1] == self._rank[id2]:
self._rank[id1] += 1
self._setCount -= 1
class Kruskal(object):
"""docstring for Kruskal"""
def __init__(self, vertexList, edgeList):
# vertexList is a list containing the names of input vertices
# edgeLIst has the format (vertexName, vertexName, edgeWeight)
self.vertexToIndex = self._mapVertexToIndex(vertexList)
self.indexToVertex = self._mapIndexToVertex(vertexList)
self.vertexList = self._makeVertexList(vertexList)
self.edgeList = self._makeEdgeList(edgeList)
self.disjointSet = DisjointSet(self.vertexList)
self.mst = []
def _mapVertexToIndex(self, vertexList):
# map the name of vertex to a unique index
vertexToIndex = dict()
count = 0
for v in vertexList:
vertexToIndex[v] = count
count += 1
return vertexToIndex
def _mapIndexToVertex(self, vertexList):
# map the name of vertex to a unique index
indexToVertex = dict()
count = 0
for v in vertexList:
indexToVertex[count] = v
count += 1
return indexToVertex
def _makeVertexList(self, vertexList):
temp = [None for v in vertexList]
for v in vertexList:
vertexId = self.vertexToIndex[v]
temp[vertexId] = vertexId
return temp
def _makeEdgeList(self, edgeList):
temp = [None for e in edgeList]
count = 0
for e in edgeList:
vertexId1 = self.vertexToIndex[e[0]]
vertexId2 = self.vertexToIndex[e[1]]
weight = e[2]
temp[count] = Edge(vertexId1, vertexId2, weight)
count += 1
return temp
def calcMST(self):
self.edgeList.sort()
for edge in self.edgeList:
v1 = edge.startVertex
v2 = edge.endVertex
id1 = self.disjointSet.find(v1)
id2 = self.disjointSet.find(v2)
if id1 != id2:
self.mst.append(edge)
self.disjointSet.union(v1, v2)
if self.disjointSet._setCount == 1:
break
return self.mst
graph = { 'V': ['A', 'B', 'C', 'D', 'E', 'F', 'G'], \
'E': [('A','B',2), ('A','C',6), ('A','E',5), ('A','F',10), ('B','D',3), \
('B','E',3), ('C','D',1), ('C','F',2), ('D','E',4), ('D','G',6), ('F','G',5)] }
test = Kruskal(graph['V'], graph['E'])
testResult = test.calcMST()
for edge in testResult:
u = test.indexToVertex[edge.startVertex]
v = test.indexToVertex[edge.endVertex]
print(u, '-', v, '=', edge.weight)
'''
for v in test.vertexList:
print(v.name)
node = v.node
while node is not None:
if node._parent is not None:
print(node.nodeID, node._parent.nodeID, node._rank)
else: print(node.nodeID, node._parent, node._rank)
node = node._parent
print(test.vertexList[test.vertexToIndex['F']].node._parent.nodeID)
test.disjointSet.find(test.vertexList[test.vertexToIndex['F']].node)
print(test.vertexList[test.vertexToIndex['F']].node._parent.nodeID)
'''