Skip to content

Commit 6eee49e

Browse files
committed
Add basic union test tests for behaviour
1 parent b084770 commit 6eee49e

1 file changed

Lines changed: 89 additions & 0 deletions

File tree

tests/test_union_find.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
from boruvkas_algorithm.boruvka import UnionFind
2+
3+
4+
def test_union_find_initialization():
5+
"""Tests that UnionFind initialises with correct parent and rank arrays."""
6+
uf = UnionFind(5)
7+
assert uf.parent == [0, 1, 2, 3, 4], "Each node should be its own parent"
8+
assert uf.rank == [1, 1, 1, 1, 1], "Each node should have rank 1"
9+
10+
11+
def test_union_find_find_single_node():
12+
"""Tests that find returns the node itself when it's its own parent."""
13+
uf = UnionFind(5)
14+
assert uf.find(0) == 0
15+
assert uf.find(4) == 4
16+
17+
18+
def test_union_find_union_two_nodes():
19+
"""Tests that union correctly combines two nodes."""
20+
uf = UnionFind(5)
21+
result = uf.union(0, 1)
22+
assert result is True, "Union should return True when nodes are combined"
23+
assert uf.find(0) == uf.find(1), "Nodes should have the same root after union"
24+
25+
26+
def test_union_find_union_already_connected():
27+
"""Tests that union returns False when nodes are already connected."""
28+
uf = UnionFind(5)
29+
uf.union(0, 1)
30+
result = uf.union(0, 1)
31+
assert result is False, "Union should return False when already connected"
32+
33+
34+
def test_union_find_union_by_size():
35+
"""Tests that smaller trees are merged into larger trees."""
36+
uf = UnionFind(5)
37+
# Create a larger tree: 0 <- 1, 0 <- 2
38+
uf.union(0, 1)
39+
uf.union(0, 2)
40+
# Now union with node 3 - node 3 should be merged into the larger tree.
41+
uf.union(3, 0)
42+
# The root of the larger tree should remain the root.
43+
root = uf.find(0)
44+
assert uf.find(3) == root, "Smaller tree should be merged into larger tree"
45+
46+
47+
def test_union_find_path_compression():
48+
"""Tests that path compression flattens the tree structure."""
49+
uf = UnionFind(5)
50+
# Create a chain: 0 <- 1 <- 2 <- 3
51+
uf.parent = [0, 0, 1, 2, 4]
52+
uf.rank = [4, 1, 1, 1, 1]
53+
# Find on node 3 should compress the path.
54+
root = uf.find(3)
55+
assert root == 0, "Root should be 0"
56+
# After path compression, intermediate nodes should point closer to root.
57+
assert uf.parent[2] in (0, 1), "Path compression should shorten the path"
58+
59+
60+
def test_union_find_multiple_components():
61+
"""Tests UnionFind with multiple separate components."""
62+
uf = UnionFind(6)
63+
# Create two components: {0, 1, 2} and {3, 4, 5}
64+
uf.union(0, 1)
65+
uf.union(1, 2)
66+
uf.union(3, 4)
67+
uf.union(4, 5)
68+
69+
# Check components are separate.
70+
assert uf.find(0) == uf.find(1) == uf.find(2)
71+
assert uf.find(3) == uf.find(4) == uf.find(5)
72+
assert uf.find(0) != uf.find(3), "Components should be separate"
73+
74+
# Merge the two components.
75+
uf.union(2, 3)
76+
assert uf.find(0) == uf.find(5), "Components should be merged"
77+
78+
79+
def test_union_find_connected():
80+
"""Tests the connected convenience method."""
81+
uf = UnionFind(5)
82+
assert not uf.is_connected(0, 1), "Nodes should not be connected initially"
83+
84+
uf.union(0, 1)
85+
assert uf.is_connected(0, 1), "Nodes should be connected after union"
86+
assert not uf.is_connected(0, 2), "Unconnected nodes should return False"
87+
88+
uf.union(1, 2)
89+
assert uf.is_connected(0, 2), "Transitively connected nodes should return True"

0 commit comments

Comments
 (0)