1+ /*
2+ * disjoint_union_set_test.cpp
3+ *
4+ * Created on: Dec 09, 2025 22:08
5+ * Description:
6+ *
7+ * Copyright (c) 2025 Pin Loon Lee (pllee4)
8+ */
9+
10+ #include " algorithm/generic/disjoint_union_set/disjoint_union_set.hpp"
11+
12+ #include " gtest/gtest.h"
13+
14+ using namespace pllee4 ::generic;
15+
16+ TEST (DisjointUnionSetsTest, InitialState) {
17+ DisjointUnionSets dsu (5 );
18+
19+ for (auto i = 0 ; i < 5 ; ++i) {
20+ EXPECT_EQ (dsu.Find (i), i)
21+ << " Element " << i << " should be its own parent initially" ;
22+ }
23+ }
24+
25+ TEST (DisjointUnionSetsTest, UnionTwoElements) {
26+ DisjointUnionSets dsu (5 );
27+
28+ dsu.UnionSets (0 , 1 );
29+
30+ EXPECT_EQ (dsu.Find (0 ), dsu.Find (1 ))
31+ << " Elements 0 and 1 should have the same root" ;
32+ }
33+
34+ TEST (DisjointUnionSetsTest, UnionChain) {
35+ DisjointUnionSets dsu (5 );
36+
37+ dsu.UnionSets (0 , 1 );
38+ dsu.UnionSets (1 , 2 );
39+ dsu.UnionSets (2 , 3 );
40+
41+ const auto root = dsu.Find (0 );
42+ EXPECT_EQ (dsu.Find (1 ), root);
43+ EXPECT_EQ (dsu.Find (2 ), root);
44+ EXPECT_EQ (dsu.Find (3 ), root);
45+ EXPECT_NE (dsu.Find (4 ), root) << " Element 4 should not be in the same set" ;
46+ }
47+
48+ TEST (DisjointUnionSetsTest, PathCompression) {
49+ DisjointUnionSets dsu (5 );
50+
51+ dsu.UnionSets (0 , 1 );
52+ dsu.UnionSets (1 , 2 );
53+ dsu.UnionSets (2 , 3 );
54+
55+ // After first Find, path should be compressed
56+ const auto root = dsu.Find (3 );
57+ EXPECT_EQ (dsu.Find (0 ), root);
58+
59+ // All elements should now point directly to root (path compression)
60+ EXPECT_EQ (dsu.Find (1 ), root);
61+ EXPECT_EQ (dsu.Find (2 ), root);
62+ }
63+
64+ TEST (DisjointUnionSetsTest, UnionByRank) {
65+ DisjointUnionSets dsu (10 );
66+
67+ // Create two trees of different ranks
68+ dsu.UnionSets (0 , 1 );
69+ dsu.UnionSets (2 , 3 );
70+ dsu.UnionSets (3 , 4 );
71+
72+ EXPECT_NE (dsu.Find (0 ), dsu.Find (2 ));
73+
74+ // Union the two trees
75+ dsu.UnionSets (0 , 2 );
76+
77+ // The tree with higher rank should become the root
78+ EXPECT_EQ (dsu.Find (4 ), dsu.Find (0 ));
79+ }
80+
81+ TEST (DisjointUnionSetsTest, UnionLowerRankToHigherRank) {
82+ DisjointUnionSets dsu (6 );
83+
84+ dsu.UnionSets (0 , 1 );
85+ dsu.UnionSets (2 , 3 );
86+ dsu.UnionSets (0 , 2 );
87+
88+ dsu.UnionSets (4 , 0 );
89+
90+ EXPECT_EQ (dsu.Find (4 ), dsu.Find (0 ));
91+ }
92+
93+ TEST (DisjointUnionSetsTest, SelfUnion) {
94+ DisjointUnionSets dsu (5 );
95+
96+ dsu.UnionSets (2 , 2 );
97+
98+ EXPECT_EQ (dsu.Find (2 ), 2 ) << " Self-union should not change the parent" ;
99+ }
100+
101+ // Test: Multiple disjoint sets
102+ TEST (DisjointUnionSetsTest, MultipleDisjointSets) {
103+ DisjointUnionSets dsu (10 );
104+
105+ dsu.UnionSets (0 , 1 );
106+ dsu.UnionSets (2 , 3 );
107+ dsu.UnionSets (4 , 5 );
108+
109+ // Check that different sets have different roots
110+ EXPECT_EQ (dsu.Find (0 ), dsu.Find (1 ));
111+ EXPECT_EQ (dsu.Find (2 ), dsu.Find (3 ));
112+ EXPECT_EQ (dsu.Find (4 ), dsu.Find (5 ));
113+
114+ EXPECT_NE (dsu.Find (0 ), dsu.Find (2 ));
115+ EXPECT_NE (dsu.Find (2 ), dsu.Find (4 ));
116+ EXPECT_NE (dsu.Find (0 ), dsu.Find (4 ));
117+ }
118+
119+ TEST (DisjointUnionSetsTest, IdempotentUnions) {
120+ DisjointUnionSets dsu (5 );
121+
122+ dsu.UnionSets (0 , 1 );
123+ const auto root1 = dsu.Find (0 );
124+
125+ dsu.UnionSets (0 , 1 );
126+ dsu.UnionSets (1 , 0 );
127+
128+ EXPECT_EQ (dsu.Find (0 ), root1)
129+ << " Repeated unions should not change the structure" ;
130+ }
131+
132+ TEST (DisjointUnionSetsTest, LargeSet) {
133+ DisjointUnionSets dsu (1000 );
134+
135+ // Union all elements into one set
136+ for (auto i = 1 ; i < 1000 ; ++i) {
137+ dsu.UnionSets (0 , i);
138+ }
139+
140+ const auto root = dsu.Find (0 );
141+ for (int i = 1 ; i < 1000 ; ++i) {
142+ EXPECT_EQ (dsu.Find (i), root) << " All elements should be in the same set" ;
143+ }
144+ }
145+
146+ TEST (DisjointUnionSetsTest, AlternatingUnions) {
147+ DisjointUnionSets dsu (8 );
148+
149+ dsu.UnionSets (0 , 2 );
150+ dsu.UnionSets (1 , 3 );
151+ dsu.UnionSets (4 , 6 );
152+ dsu.UnionSets (5 , 7 );
153+
154+ dsu.UnionSets (0 , 4 );
155+ dsu.UnionSets (1 , 5 );
156+
157+ dsu.UnionSets (0 , 1 );
158+
159+ // All should be in the same set now
160+ const auto root = dsu.Find (0 );
161+ for (int i = 1 ; i < 8 ; ++i) {
162+ EXPECT_EQ (dsu.Find (i), root);
163+ }
164+ }
0 commit comments