Skip to content

Commit 655661a

Browse files
srkchowdary2000shermanhui
authored andcommitted
Added Borůvka's algorithm. (TheAlgorithms#4645)
* Added Borůvka's algorithm. * Added Borůvka's algorithm, a graph algorithm that finds the minimum spanning tree. * Added Borůvka's algorithm, a graph algorithm that finds the minimum spanning tree. * Added Borůvka's algorithm, a graph algorithm that finds the minimum spanning tree. * Added Borůvka's algorithm, a graph algorithm that finds the minimum spanning tree. * Added Borůvka's algorithm, a graph algorithm that finds the minimum spanning tree. Solved Test Cases Errors. * Added Borůvka's algorithm, a graph algorithm that finds the minimum spanning tree. Solved Test Cases Errors. * Added Borůvka's algorithm, a graph algorithm that finds the minimum spanning tree. Solved Test Cases Errors. * Added Borůvka's algorithm, a graph algorithm that finds the minimum spanning tree. Solved Test Cases Errors. * Added Borůvka's algorithm, a graph algorithm that finds the minimum spanning tree. Solved Test Cases Errors. * Added Borůvka's algorithm, a graph algorithm that finds the minimum spanning tree. Solved Test Cases Errors. * Added Borůvka's algorithm, a graph algorithm that finds the minimum spanning tree. Solved Test Cases Errors.Removed WhiteSpaces. * Added Borůvka's algorithm, a graph algorithm that finds the minimum spanning tree. Code Changes. * Added Borůvka's algorithm, a graph algorithm that finds the minimum spanning tree. Code Changes.
1 parent 0c23f30 commit 655661a

File tree

1 file changed

+198
-0
lines changed

1 file changed

+198
-0
lines changed

graphs/boruvka.py

+198
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
"""Borůvka's algorithm.
2+
3+
Determines the minimum spanning tree(MST) of a graph using the Borůvka's algorithm.
4+
Borůvka's algorithm is a greedy algorithm for finding a minimum spanning tree in a
5+
graph,or a minimum spanning forest in the case of a graph that is not connected.
6+
7+
The time complexity of this algorithm is O(ELogV), where E represents the number
8+
of edges, while V represents the number of nodes.
9+
10+
The space complexity of this algorithm is O(V + E), since we have to keep a couple
11+
of lists whose sizes are equal to the number of nodes, as well as keep all the
12+
edges of a graph inside of the data structure itself.
13+
14+
Borůvka's algorithm gives us pretty much the same result as other MST Algorithms -
15+
they all find the minimum spanning tree, and the time complexity is approximately
16+
the same.
17+
18+
One advantage that Borůvka's algorithm has compared to the alternatives is that it
19+
doesn't need to presort the edges or maintain a priority queue in order to find the
20+
minimum spanning tree.
21+
Even though that doesn't help its complexity, since it still passes the edges logE
22+
times, it is a bit more simple to code.
23+
24+
Details: https://en.wikipedia.org/wiki/Bor%C5%AFvka%27s_algorithm
25+
"""
26+
27+
28+
class Graph:
29+
def __init__(self, num_of_nodes: int) -> None:
30+
"""
31+
Arguments:
32+
num_of_nodes - the number of nodes in the graph
33+
Attributes:
34+
m_v - the number of nodes in the graph.
35+
m_edges - the list of edges.
36+
m_component - the dictionary which stores the index of the component which
37+
a node belongs to.
38+
"""
39+
40+
self.m_v = num_of_nodes
41+
self.m_edges = []
42+
self.m_component = {}
43+
44+
def add_edge(self, u_node: int, v_node: int, weight: int) -> None:
45+
"""Adds an edge in the format [first, second, edge weight] to graph."""
46+
47+
self.m_edges.append([u_node, v_node, weight])
48+
49+
def find_component(self, u_node: int) -> int:
50+
"""Propagates a new component throughout a given component."""
51+
52+
if self.m_component[u_node] == u_node:
53+
return u_node
54+
return self.find_component(self.m_component[u_node])
55+
56+
def set_component(self, u_node: int) -> None:
57+
"""Finds the component index of a given node"""
58+
59+
if self.m_component[u_node] != u_node:
60+
for k in self.m_component.keys():
61+
self.m_component[k] = self.find_component(k)
62+
63+
def union(self, component_size: list, u_node: int, v_node: int) -> None:
64+
"""Union finds the roots of components for two nodes, compares the components
65+
in terms of size, and attaches the smaller one to the larger one to form
66+
single component"""
67+
68+
if component_size[u_node] <= component_size[v_node]:
69+
self.m_component[u_node] = v_node
70+
component_size[v_node] += component_size[u_node]
71+
self.set_component(u_node)
72+
73+
elif component_size[u_node] >= component_size[v_node]:
74+
self.m_component[v_node] = self.find_component(u_node)
75+
component_size[u_node] += component_size[v_node]
76+
self.set_component(v_node)
77+
78+
def boruvka(self) -> None:
79+
"""Performs Borůvka's algorithm to find MST."""
80+
81+
# Initialize additional lists required to algorithm.
82+
component_size = []
83+
mst_weight = 0
84+
85+
minimum_weight_edge = [-1] * self.m_v
86+
87+
# A list of components (initialized to all of the nodes)
88+
for node in range(self.m_v):
89+
self.m_component.update({node: node})
90+
component_size.append(1)
91+
92+
num_of_components = self.m_v
93+
94+
while num_of_components > 1:
95+
l_edges = len(self.m_edges)
96+
for i in range(l_edges):
97+
98+
u = self.m_edges[i][0]
99+
v = self.m_edges[i][1]
100+
w = self.m_edges[i][2]
101+
102+
u_component = self.m_component[u]
103+
v_component = self.m_component[v]
104+
105+
if u_component != v_component:
106+
"""If the current minimum weight edge of component u doesn't
107+
exist (is -1), or if it's greater than the edge we're
108+
observing right now, we will assign the value of the edge
109+
we're observing to it.
110+
111+
If the current minimum weight edge of component v doesn't
112+
exist (is -1), or if it's greater than the edge we're
113+
observing right now, we will assign the value of the edge
114+
we're observing to it"""
115+
116+
if (
117+
minimum_weight_edge[u_component] == -1
118+
or minimum_weight_edge[u_component][2] > w
119+
):
120+
minimum_weight_edge[u_component] = [u, v, w]
121+
if (
122+
minimum_weight_edge[v_component] == -1
123+
or minimum_weight_edge[v_component][2] > w
124+
):
125+
minimum_weight_edge[v_component] = [u, v, w]
126+
127+
for node in range(self.m_v):
128+
if minimum_weight_edge[node] != -1:
129+
u = minimum_weight_edge[node][0]
130+
v = minimum_weight_edge[node][1]
131+
w = minimum_weight_edge[node][2]
132+
133+
u_component = self.m_component[u]
134+
v_component = self.m_component[v]
135+
136+
if u_component != v_component:
137+
mst_weight += w
138+
self.union(component_size, u_component, v_component)
139+
print(
140+
"Added edge ["
141+
+ str(u)
142+
+ " - "
143+
+ str(v)
144+
+ "]\n"
145+
+ "Added weight: "
146+
+ str(w)
147+
+ "\n"
148+
)
149+
num_of_components -= 1
150+
151+
minimum_weight_edge = [-1] * self.m_v
152+
print("The total weight of the minimal spanning tree is: " + str(mst_weight))
153+
154+
155+
def test_vector() -> None:
156+
"""
157+
>>> g=Graph(8)
158+
>>> g.add_edge(0, 1, 10)
159+
>>> g.add_edge(0, 2, 6)
160+
>>> g.add_edge(0, 3, 5)
161+
>>> g.add_edge(1, 3, 15)
162+
>>> g.add_edge(2, 3, 4)
163+
>>> g.add_edge(3, 4, 8)
164+
>>> g.add_edge(4, 5, 10)
165+
>>> g.add_edge(4, 6, 6)
166+
>>> g.add_edge(4, 7, 5)
167+
>>> g.add_edge(5, 7, 15)
168+
>>> g.add_edge(6, 7, 4)
169+
>>> g.boruvka()
170+
Added edge [0 - 3]
171+
Added weight: 5
172+
<BLANKLINE>
173+
Added edge [0 - 1]
174+
Added weight: 10
175+
<BLANKLINE>
176+
Added edge [2 - 3]
177+
Added weight: 4
178+
<BLANKLINE>
179+
Added edge [4 - 7]
180+
Added weight: 5
181+
<BLANKLINE>
182+
Added edge [4 - 5]
183+
Added weight: 10
184+
<BLANKLINE>
185+
Added edge [6 - 7]
186+
Added weight: 4
187+
<BLANKLINE>
188+
Added edge [3 - 4]
189+
Added weight: 8
190+
<BLANKLINE>
191+
The total weight of the minimal spanning tree is: 46
192+
"""
193+
194+
195+
if __name__ == "__main__":
196+
import doctest
197+
198+
doctest.testmod()

0 commit comments

Comments
 (0)