1
+ # Basic implementation of the Union Find data structure
2
+ # Assume we have n nodes labeled from 0 to n - 1
3
+
4
+ class UnionFind :
5
+ def __init__ (self , n ):
6
+ # every node is originally its own parent
7
+ self .par = [i for i in range (n )]
8
+ # self.par = list(range(n)) -- also valid
9
+
10
+ # every node originally is in its own
11
+ # component of size 1 - this changes during
12
+ # the union operation
13
+ self .rank = [1 ] * n
14
+
15
+ def find (self , n ) -> int :
16
+ '''
17
+ Finds the parent node of n
18
+ '''
19
+
20
+ # can be optimized with path compression
21
+ while n != self .par [n ]:
22
+ n = self .par [n ]
23
+ return n
24
+
25
+
26
+ def union (self , n1 , n2 ) -> bool :
27
+ '''
28
+ Connects two nodes together if not
29
+ already connected
30
+ '''
31
+
32
+ # find the parent of node 1 and 2
33
+ p1 = self .find (n1 )
34
+ p2 = self .find (n2 )
35
+
36
+ # nodes are already connected
37
+ # cannot union together
38
+ if p1 == p2 :
39
+ return False
40
+
41
+ # for efficiency, make bigger component
42
+ # parent of smaller component - reduces
43
+ # number of steps we have to take in find()
44
+
45
+ if self .rank [p1 ] >= self .rank [p2 ]:
46
+ # p2 is smaller, so when union it has a
47
+ # new parent, p1
48
+ self .par [p2 ] = p1
49
+
50
+ # p1 gets all the nodes of p2, increasing
51
+ # its rank, or size
52
+ self .rank [p1 ] += self .rank [p2 ]
53
+ else :
54
+ self .par [p1 ] = p2
55
+ self .rank [p2 ] += self .rank [p1 ]
56
+
57
+ return True
58
+
59
+ def nodes_connected (self , n1 , n2 ) -> bool :
60
+ '''
61
+ Returns if two nodes are connected
62
+ '''
63
+
64
+ # connected if parent is the same
65
+ return self .find (n1 ) == self .find (n2 )
66
+
67
+
68
+
69
+ def verify ():
70
+ n = 7
71
+ u = UnionFind (n )
72
+
73
+ # False, nodes not connected
74
+ print (u .nodes_connected (0 , 1 ))
75
+
76
+ # True, just connected 0 and 1
77
+ u .union (0 , 1 )
78
+ print (u .nodes_connected (0 , 1 ))
79
+
80
+ # Rank is 2, includes 0 and 1
81
+ print (u .rank [0 ])
82
+
83
+ u .union (4 , 5 )
84
+ u .union (1 , 4 )
85
+
86
+ # True, 0 - 1 and 4 - 5 are connected
87
+ # 1 to 4 connects both components
88
+ print (u .nodes_connected (0 , 5 ))
0 commit comments