Skip to content

Commit 4520d84

Browse files
committed
added Union Find progression basic, path_compression, quickfind, quickunion, optimized
1 parent 586da8c commit 4520d84

File tree

6 files changed

+205
-0
lines changed

6 files changed

+205
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# The vey basics of union find and disjoint sets
2+
# Basically an array and within that array lies a disjoint set
3+
4+
5+
# There are two functions when discussing disjoint sets
6+
7+
# find(a) which takes in a single argument and returns the root of
8+
# that particular node
9+
10+
# union(a,b) which takes in two arguments and combines them together
11+
# let's watch a quick video on how this works and then implement from there
12+
13+
# First lets implement UnionFind as an object and instantiate it with an array
14+
15+
class UnionFind:
16+
def __init__(self, size):
17+
self.root = [i for i in range(size)]
18+
19+
# union connects two nodes with a left bias meaning that b will always
20+
# connect to a
21+
def union(self, x, y):
22+
rootX = self.find(x)
23+
rootY = self.find(y)
24+
if rootX != rootY:
25+
for i in range(len(self.root)):
26+
if self.root[i] == rootY:
27+
self.root[i] = rootX
28+
29+
# takes in a node a and returns the root node of such
30+
def find(self, a):
31+
while a != self.root[a]:
32+
a = self.root[a]
33+
return a
34+
35+
uu = UnionFind(10)
36+
37+
print(uu.root)
38+
uu.union(0,1)
39+
uu.union(0,2)
40+
uu.union(1,3)
41+
uu.union(4,8)
42+
uu.union(5,6)
43+
uu.union(5,7)
44+
print(uu.root)
45+
print([i for i in range(10)])
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
2+
class UnionFind:
3+
def __init__(self,size):
4+
self.root = [i for i in range(size)]
5+
6+
def find(self, n):
7+
if self.root[n] == n:
8+
return n
9+
10+
self.root[n] = self.find(self.root[n])
11+
return self.root[n]
12+
# quick union
13+
def union(self, a, b):
14+
fa = self.find(a)
15+
fb = self.find(b)
16+
if fa != fb:
17+
self.root[fa] = fb
18+
19+
def connected(self, x, y):
20+
return self.find(x) == self.find(y)
21+
# Test Case
22+
uf = UnionFind(10)
23+
# 1-2-5-6-7 3-8-9 4
24+
uf.union(1, 2)
25+
uf.union(2, 5)
26+
uf.union(5, 6)
27+
uf.union(6, 7)
28+
uf.union(3, 8)
29+
uf.union(8, 9)
30+
print(uf.connected(1, 5)) # true
31+
print(uf.connected(5, 7)) # true
32+
print(uf.connected(4, 9)) # false
33+
# 1-2-5-6-7 3-8-9-4
34+
uf.union(9, 4)
35+
print(uf.connected(4, 9)) # true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
class UnionFind:
2+
def __init__(self, size):
3+
self.root = [i for i in range(size)]
4+
# changing quickfind to have the parent node be stored in the array
5+
# effectively making it an O(1) operation to find the root of a given node
6+
# however, union will take a hit in performance
7+
8+
def find(self, n):
9+
return self.root[n]
10+
11+
def union(self, a, b):
12+
fa = self.find(a)
13+
fb = self.find(b)
14+
if fa != fb:
15+
for i, v in enumerate(self.root):
16+
if fa == v:
17+
self.root[i] = fb
18+
19+
def connected(self, x, y):
20+
return self.find(x) == self.find(y)
21+
22+
23+
# Test Case
24+
uf = UnionFind(10)
25+
# 1-2-5-6-7 3-8-9 4
26+
uf.union(1, 2)
27+
uf.union(2, 5)
28+
uf.union(5, 6)
29+
uf.union(6, 7)
30+
uf.union(3, 8)
31+
uf.union(8, 9)
32+
print(uf.connected(1, 5)) # true
33+
print(uf.connected(5, 7)) # true
34+
print(uf.connected(4, 9)) # false
35+
# 1-2-5-6-7 3-8-9-4
36+
uf.union(9, 4)
37+
print(uf.connected(4, 9)) # true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# The vey basics of union find and disjoint sets
2+
# Basically an array and within that array lies a disjoint set
3+
4+
5+
# There are two functions when discussing disjoint sets
6+
7+
# find(a) which takes in a single argument and returns the root of
8+
# that particular node
9+
10+
# union(a,b) which takes in two arguments and combines them together
11+
# let's watch a quick video on how this works and then implement from there
12+
13+
# First lets implement UnionFind as an object and instantiate it with an array
14+
15+
class UnionFind:
16+
def __init__(self, size):
17+
self.root = [i for i in range(size)]
18+
19+
# union connects two nodes with a left bias meaning that b will always
20+
# connect to a
21+
def union(self,a,b):
22+
# Basically we want to take the parent node of the given thing
23+
fa = self.find(a)
24+
fb = self.find(b)
25+
if fa != fb:
26+
self.root[fa] = fb
27+
28+
# takes in a node a and returns the root node of such
29+
def find(self, a):
30+
while a != self.root[a]:
31+
a = self.root[a]
32+
return a
33+
34+
uu = UnionFind(10)
35+
36+
print(uu.root)
37+
uu.union(0,1)
38+
uu.union(0,2)
39+
uu.union(1,3)
40+
uu.union(4,8)
41+
uu.union(5,6)
42+
uu.union(5,7)
43+
print(uu.root)
44+
print([i for i in range(10)])
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Optimized union find program that implements union by rank
2+
3+
class UnionFind:
4+
def __init__(self, size):
5+
self.root = [i for i in range(size)]
6+
self.rank = [1] * size
7+
8+
# Recurrsively update root
9+
def find(self, n):
10+
if self.root[n] != n:
11+
self.root[n] = self.find(self.root[n])
12+
return self.root[n]
13+
14+
def union(self, a, b):
15+
fa = self.find(a)
16+
fb = self.find(b)
17+
18+
if fa != fb:
19+
if self.rank[fa] > self.rank[fb]:
20+
self.root[fb] = fa
21+
elif self.rank[fa] < self.rank[fb]:
22+
self.root[fa] = fb
23+
else:
24+
self.root[fa] = fb
25+
self.rank[fb] += 1
26+
27+
def connected(self, x, y):
28+
return self.find(x) == self.find(y)
29+
30+
# Test Case
31+
uf = UnionFind(10)
32+
# 1-2-5-6-7 3-8-9 4
33+
uf.union(1, 2)
34+
uf.union(2, 5)
35+
uf.union(5, 6)
36+
uf.union(6, 7)
37+
uf.union(3, 8)
38+
uf.union(8, 9)
39+
print(uf.connected(1, 5)) # true
40+
print(uf.connected(5, 7)) # true
41+
print(uf.connected(4, 9)) # false
42+
# 1-2-5-6-7 3-8-9-4
43+
uf.union(9, 4)
44+
print(uf.connected(4, 9)) # true

Graphs/UnionFind/DisjointSet/README.md

Whitespace-only changes.

0 commit comments

Comments
 (0)