Introduction to Disjoint Set (Union-Find Data Structure)
Last Updated :
24 Jul, 2025
Two sets are called disjoint sets if they don't have any element in common. The disjoint set data structure is used to store such sets. It supports following operations:
- Merging two disjoint sets to a single set using Union operation.
- Finding representative of a disjoint set using Find operation.
- Check if two elements belong to same set or not. We mainly find representative of both and check if same.
Consider a situation with a number of persons and the following tasks to be performed on them:
- Add a new friendship relation, i.e. a person x becomes the friend of another person y i.e adding new element to a set.
- Find whether individual x is a friend of individual y (direct or indirect friend)
Examples:
We are given 10 individuals say, a, b, c, d, e, f, g, h, i, j
Following are relationships to be added:
a <-> b
b <-> d
c <-> f
c <-> i
j <-> e
g <-> j
Given queries like whether a is a friend of d or not. We basically need to create following 4 groups and maintain a quickly accessible connection among group items:
G1 = {a, b, d}
G2 = {c, f, i}
G3 = {e, g, j}
G4 = {h}
Find whether x and y belong to the same group or not, i.e. to find if x and y are direct/indirect friends.
Partitioning the individuals into different sets according to the groups in which they fall. This method is known as a Disjoint set Union which maintains a collection of Disjoint sets and each set is represented by one of its members.
To answer the above question two key points to be considered are:
- How to Resolve sets? Initially, all elements belong to different sets. After working on the given relations, we select a member as a representative.
- Check if 2 persons are in the same group? If representatives of two individuals are the same, then they are friends.
Data Structures used are:
Array: An array of integers is called Parent[]. If we are dealing with N items, i'th element of the array represents the i'th item. More precisely, the i'th element of the Parent[] array is the parent of the i'th item. These relationships create one or more virtual trees.
Tree: It is a Disjoint set. If two elements are in the same tree, then they are in the same Disjoint set. The root node (or the topmost node) of each tree is called the representative of the set. There is always a single unique representative of each set. A simple rule to identify a representative is if 'i' is the representative of a set, then Parent[i] = i. If i is not the representative of his set, then it can be found by traveling up the tree until we find the representative.
Operations on Disjoint Set Data Structures:
1. Find:
The task is to find representative of the set of a given element. The representative is always root of the tree. So we implement find() by recursively traversing the parent array until we hit a node that is root (parent of itself).
2. Union:
The task is to combine two sets and make one. It takes two elements as input and finds the representatives of their sets using the Find operation, and finally puts either one of the trees (representing the set) under the root node of the other tree.
C++
#include <iostream>
#include <vector>
using namespace std;
class UnionFind {
vector<int> parent;
public:
UnionFind(int size) {
parent.resize(size);
// Initialize the parent array with each
// element as its own representative
for (int i = 0; i < size; i++) {
parent[i] = i;
}
}
// Find the representative (root) of the
// set that includes element i
int find(int i) {
// If i itself is root or representative
if (parent[i] == i) {
return i;
}
// Else recursively find the representative
// of the parent
return find(parent[i]);
}
// Unite (merge) the set that includes element
// i and the set that includes element j
void unite(int i, int j) {
// Representative of set containing i
int irep = find(i);
// Representative of set containing j
int jrep = find(j);
// Make the representative of i's set
// be the representative of j's set
parent[irep] = jrep;
}
};
int main() {
int size = 5;
UnionFind uf(size);
uf.unite(1, 2);
uf.unite(3, 4);
bool inSameSet = (uf.find(1) == uf.find(2));
cout << "Are 1 and 2 in the same set? "
<< (inSameSet ? "Yes" : "No") << endl;
return 0;
}
Java
import java.util.Arrays;
public class UnionFind {
private int[] parent;
public UnionFind(int size) {
// Initialize the parent array with each
// element as its own representative
parent = new int[size];
for (int i = 0; i < size; i++) {
parent[i] = i;
}
}
// Find the representative (root) of the
// set that includes element i
public int find(int i) {
// if i itself is root or representative
if (parent[i] == i) {
return i;
}
// Else recursively find the representative
// of the parent
return find(parent[i]);
}
// Unite (merge) the set that includes element
// i and the set that includes element j
public void union(int i, int j) {
// Representative of set containing i
int irep = find(i);
// Representative of set containing j
int jrep = find(j);
// Make the representative of i's set be
// the representative of j's set
parent[irep] = jrep;
}
public static void main(String[] args) {
int size = 5;
UnionFind uf = new UnionFind(size);
uf.union(1, 2);
uf.union(3, 4);
boolean inSameSet = uf.find(1) == uf.find(2);
System.out.println("Are 1 and 2 in the same set? " + inSameSet);
}
}
Python
class UnionFind:
def __init__(self, size):
# Initialize the parent array with each
# element as its own representative
self.parent = list(range(size))
def find(self, i):
# If i itself is root or representative
if self.parent[i] == i:
return i
# Else recursively find the representative
# of the parent
return self.find(self.parent[i])
def unite(self, i, j):
# Representative of set containing i
irep = self.find(i)
# Representative of set containing j
jrep = self.find(j)
# Make the representative of i's set
# be the representative of j's set
self.parent[irep] = jrep
# Example usage
size = 5
uf = UnionFind(size)
uf.unite(1, 2)
uf.unite(3, 4)
in_same_set = (uf.find(1) == uf.find(2))
print("Are 1 and 2 in the same set?", "Yes" if in_same_set else "No")
C#
using System;
public class UnionFind {
private int[] parent;
public UnionFind(int size) {
// Initialize the parent array with each
// element as its own representative
parent = new int[size];
for (int i = 0; i < size; i++) {
parent[i] = i;
}
}
// Find the representative (root) of the
// set that includes element i
public int Find(int i) {
// If i itself is root or representative
if (parent[i] == i) {
return i;
}
// Else recursively find the representative
// of the parent
return Find(parent[i]);
}
// Unite (merge) the set that includes element
// i and the set that includes element j
public void Union(int i, int j) {
// Representative of set containing i
int irep = Find(i);
// Representative of set containing j
int jrep = Find(j);
// Make the representative of i's set be
// the representative of j's set
parent[irep] = jrep;
}
public static void Main(string[] args) {
int size = 5;
UnionFind uf = new UnionFind(size);
uf.Union(1, 2);
uf.Union(3, 4);
bool inSameSet = uf.Find(1) == uf.Find(2);
Console.WriteLine("Are 1 and 2 in the same set? " +
(inSameSet ? "Yes" : "No"));
}
}
JavaScript
class UnionFind {
constructor(size) {
// Initialize the parent array with each
// element as its own representative
this.parent = Array.from({ length: size }, (_, i) => i);
}
find(i) {
// If i itself is root or representative
if (this.parent[i] === i) {
return i;
}
// Else recursively find the representative
// of the parent
return this.find(this.parent[i]);
}
unite(i, j) {
// Representative of set containing i
const irep = this.find(i);
// Representative of set containing j
const jrep = this.find(j);
// Make the representative of i's set
// be the representative of j's set
this.parent[irep] = jrep;
}
}
// Example usage
const size = 5;
const uf = new UnionFind(size);
// Unite sets containing 1 and 2, and 3 and 4
uf.unite(1, 2);
uf.unite(3, 4);
// Check if 1 and 2 are in the same set
const inSameSet = uf.find(1) === uf.find(2);
console.log("Are 1 and 2 in the same set?",
inSameSet ? "Yes" : "No");
OutputAre 1 and 2 in the same set? Yes
The above union() and find() are naive and the worst case time complexity is linear. The trees created to represent subsets can be skewed and can become like a linked list. Following is an example of worst case scenario.
Optimization (Path Compression and Union by Rank/Size):
The main idea is to reduce heights of trees representing different sets. We achieve this with two most common methods:
1) Path Compression
2) Union By Rank
Path Compression (Used to improve find()):
The idea is to flatten the tree when find() is called. When find() is called for an element x, root of the tree is returned. The find() operation traverses up from x to find root. The idea of path compression is to make the found root as parent of x so that we don’t have to traverse all intermediate nodes again. If x is root of a subtree, then path (to root) from all nodes under x also compresses.
It speeds up the data structure by compressing the height of the trees. It can be achieved by inserting a small caching mechanism into the Find operation. Take a look at the code for more details:
Union by Rank (Modifications to union())
Rank is like height of the trees representing different sets. We use an extra array of integers called rank[]. The size of this array is the same as the parent array Parent[]. If i is a representative of a set, rank[i] is the rank of the element i. Rank is same as height if path compression is not used. With path compression, rank can be more than the actual height.
Now recall that in the Union operation, it doesn’t matter which of the two trees is moved under the other. Now what we want to do is minimize the height of the resulting tree. If we are uniting two trees (or sets), let’s call them left and right, then it all depends on the rank of left and the rank of right.
- If the rank of left is less than the rank of right, then it’s best to move left under right, because that won’t change the rank of right (while moving right under left would increase the height). In the same way, if the rank of right is less than the rank of left, then we should move right under left.
- If the ranks are equal, it doesn’t matter which tree goes under the other, but the rank of the result will always be one greater than the rank of the trees.
C++
#include <iostream>
#include <vector>
using namespace std;
class DisjointUnionSets {
vector<int> rank, parent;
public:
// Constructor to initialize sets
DisjointUnionSets(int n) {
rank.resize(n, 0);
parent.resize(n);
// Initially, each element is in its own set
for (int i = 0; i < n; i++) {
parent[i] = i;
}
}
// Find the representative of the set that x belongs to
int find(int i) {
int root = parent[i];
if (parent[root] != root) {
return parent[i] = find(root);
}
return root;
}
// Union of sets containing x and y
void unionSets(int x, int y) {
int xRoot = find(x);
int yRoot = find(y);
// If they are in the same set, no need to union
if (xRoot == yRoot) return;
// Union by rank
if (rank[xRoot] < rank[yRoot]) {
parent[xRoot] = yRoot;
} else if (rank[yRoot] < rank[xRoot]) {
parent[yRoot] = xRoot;
} else {
parent[yRoot] = xRoot;
rank[xRoot]++;
}
}
};
int main() {
// Let there be 5 persons with ids 0, 1, 2, 3, and 4
int n = 5;
DisjointUnionSets dus(n);
// 0 is a friend of 2
dus.unionSets(0, 2);
// 4 is a friend of 2
dus.unionSets(4, 2);
// 3 is a friend of 1
dus.unionSets(3, 1);
// Check if 4 is a friend of 0
if (dus.find(4) == dus.find(0))
cout << "Yes\n";
else
cout << "No\n";
// Check if 1 is a friend of 0
if (dus.find(1) == dus.find(0))
cout << "Yes\n";
else
cout << "No\n";
return 0;
}
Java
// A Java program to implement Disjoint Set with
// Path Compression and Union by Rank
import java.io.*;
import java.util.*;
class DisjointUnionSets {
int[] rank, parent;
int n;
// Constructor
public DisjointUnionSets(int n)
{
rank = new int[n];
parent = new int[n];
this.n = n;
for (int i = 0; i < n; i++) {
// Initially, all elements are in
// their own set.
parent[i] = i;
}
}
// Returns representative of x's set
public int find(int i) {
int root = parent[i];
if (parent[root] != root) {
return parent[i] = find(root);
}
return root;
}
// Unites the set that includes x and the set
// that includes x
void union(int x, int y)
{
// Find representatives of two sets
int xRoot = find(x), yRoot = find(y);
// Elements are in the same set, no need
// to unite anything.
if (xRoot == yRoot)
return;
// If x's rank is less than y's rank
if (rank[xRoot] < rank[yRoot])
// Then move x under y so that depth
// of tree remains less
parent[xRoot] = yRoot;
// Else if y's rank is less than x's rank
else if (rank[yRoot] < rank[xRoot])
// Then move y under x so that depth of
// tree remains less
parent[yRoot] = xRoot;
else // if ranks are the same
{
// Then move y under x (doesn't matter
// which one goes where)
parent[yRoot] = xRoot;
// And increment the result tree's
// rank by 1
rank[xRoot] = rank[xRoot] + 1;
}
}
}
// Driver code
public class Main {
public static void main(String[] args)
{
// Let there be 5 persons with ids as
// 0, 1, 2, 3 and 4
int n = 5;
DisjointUnionSets dus =
new DisjointUnionSets(n);
// 0 is a friend of 2
dus.union(0, 2);
// 4 is a friend of 2
dus.union(4, 2);
// 3 is a friend of 1
dus.union(3, 1);
// Check if 4 is a friend of 0
if (dus.find(4) == dus.find(0))
System.out.println("Yes");
else
System.out.println("No");
// Check if 1 is a friend of 0
if (dus.find(1) == dus.find(0))
System.out.println("Yes");
else
System.out.println("No");
}
}
Python
class DisjointUnionSets:
def __init__(self, n):
self.rank = [0] * n
self.parent = list(range(n))
def find(self, i):
root = self.parent[i]
if self.parent[root] != root:
self.parent[i] = self.find(root)
return self.parent[i]
return root
def unionSets(self, x, y):
xRoot = self.find(x)
yRoot = self.find(y)
if xRoot == yRoot:
return
# Union by Rank
if self.rank[xRoot] < self.rank[yRoot]:
self.parent[xRoot] = yRoot
elif self.rank[yRoot] < self.rank[xRoot]:
self.parent[yRoot] = xRoot
else:
self.parent[yRoot] = xRoot
self.rank[xRoot] += 1
if __name__ == '__main__':
n = 5 # Let there be 5 persons with ids 0, 1, 2, 3, and 4
dus = DisjointUnionSets(n)
dus.unionSets(0, 2) # 0 is a friend of 2
dus.unionSets(4, 2) # 4 is a friend of 2
dus.unionSets(3, 1) # 3 is a friend of 1
# Check if 4 is a friend of 0
if dus.find(4) == dus.find(0):
print('Yes')
else:
print('No')
# Check if 1 is a friend of 0
if dus.find(1) == dus.find(0):
print('Yes')
else:
print('No')
C#
// A C# program to implement Disjoint Set with
// Path Compression and Union by Rank
using System;
class DisjointUnionSets {
int[] rank, parent;
int n;
// Constructor
public DisjointUnionSets(int n)
{
rank = new int[n];
parent = new int[n];
this.n = n;
for (int i = 0; i < n; i++) {
// Initially, all elements are in
// their own set.
parent[i] = i;
}
}
// Returns representative of x's set
public int find(int i) {
int root = parent[i];
if (parent[root] != root) {
return parent[i] = find(root);
}
return root;
}
// Unites the set that includes x and the set
// that includes y
public void union(int x, int y)
{
// Find representatives of two sets
int xRoot = find(x), yRoot = find(y);
// Elements are in the same set, no need
// to unite anything.
if (xRoot == yRoot)
return;
// If x's rank is less than y's rank
if (rank[xRoot] < rank[yRoot])
// Then move x under y so that depth
// of tree remains less
parent[xRoot] = yRoot;
// Else if y's rank is less than x's rank
else if (rank[yRoot] < rank[xRoot])
// Then move y under x so that depth of
// tree remains less
parent[yRoot] = xRoot;
else // if ranks are the same
{
// Then move y under x (doesn't matter
// which one goes where)
parent[yRoot] = xRoot;
// And increment the result tree's
// rank by 1
rank[xRoot] = rank[xRoot] + 1;
}
}
}
// Driver code
class Program {
static void Main(string[] args)
{
// Let there be 5 persons with ids as
// 0, 1, 2, 3 and 4
int n = 5;
DisjointUnionSets dus = new DisjointUnionSets(n);
// 0 is a friend of 2
dus.union(0, 2);
// 4 is a friend of 2
dus.union(4, 2);
// 3 is a friend of 1
dus.union(3, 1);
// Check if 4 is a friend of 0
if (dus.find(4) == dus.find(0))
Console.WriteLine("Yes");
else
Console.WriteLine("No");
// Check if 1 is a friend of 0
if (dus.find(1) == dus.find(0))
Console.WriteLine("Yes");
else
Console.WriteLine("No");
}
}
JavaScript
class DisjointUnionSets {
constructor(n) {
this.rank = new Array(n).fill(0);
this.parent = Array.from({length: n}, (_, i) => i);
// Initially, each element is in its own set
}
find(i) {
let root = this.parent[i];
if (this.parent[root] !== root) {
return this.parent[i] = this.find(root);
}
return root;
}
unionSets(x, y) {
const xRoot = this.find(x);
const yRoot = this.find(y);
// If they are in the same set, no need to union
if (xRoot === yRoot) return;
// Union by rank
if (this.rank[xRoot] < this.rank[yRoot]) {
this.parent[xRoot] = yRoot;
} else if (this.rank[yRoot] < this.rank[xRoot]) {
this.parent[yRoot] = xRoot;
} else {
this.parent[yRoot] = xRoot;
this.rank[xRoot]++;
}
}
}
const n = 5; // Let there be 5 persons with ids 0, 1, 2, 3, and 4
const dus = new DisjointUnionSets(n);
// 0 is a friend of 2
dus.unionSets(0, 2);
// 4 is a friend of 2
dus.unionSets(4, 2);
// 3 is a friend of 1
dus.unionSets(3, 1);
// Check if 4 is a friend of 0
if (dus.find(4) === dus.find(0))
console.log('Yes');
else
console.log('No');
// Check if 1 is a friend of 0
if (dus.find(1) === dus.find(0))
console.log('Yes');
else
console.log('No');
Time complexity: O(n) for creating n single item sets . The two techniques -path compression with the union by rank/size, the time complexity will reach nearly constant time. It turns out, that the final amortized time complexity is O(α(n)), where α(n) is the inverse Ackermann function, which grows very steadily (it does not even exceed for n<10600 approximately).
Space complexity: O(n) because we need to store n elements in the Disjoint Set Data Structure.
Union by Size (Alternate of Union by Rank)
We use an array of integers called size[]. The size of this array is the same as the parent array Parent[]. If i is a representative of a set, size[i] is the number of the elements in the tree representing the set.
Now we are uniting two trees (or sets), let’s call them left and right, then in this case it all depends on the size of left and the size of right tree (or set).
- If the size of left is less than the size of right, then it’s best to move left under right and increase size of right by size of left. In the same way, if the size of right is less than the size of left, then we should move right under left. and increase size of left by size of right.
- If the sizes are equal, it doesn’t matter which tree goes under the other.
C++
// C++ program for Union by Size with Path Compression
#include <iostream>
#include <vector>
using namespace std;
class UnionFind {
vector<int> Parent;
vector<int> Size;
public:
UnionFind(int n) {
Parent.resize(n);
for (int i = 0; i < n; i++) {
Parent[i] = i;
}
// Initialize Size array with 1s
Size.resize(n, 1);
}
// Function to find the representative (or the root
// node) for the set that includes i
int find(int i) {
int root = Parent[i];
if (Parent[root] != root) {
return Parent[i] = find(root);
}
return root;
}
// Unites the set that includes i and the set that
// includes j by size
void unionBySize(int i, int j) {
// Find the representatives (or the root nodes) for
// the set that includes i
int irep = find(i);
// And do the same for the set that includes j
int jrep = find(j);
// Elements are in the same set, no need to unite
// anything.
if (irep == jrep)
return;
// Get the size of i’s tree
int isize = Size[irep];
// Get the size of j’s tree
int jsize = Size[jrep];
// If i’s size is less than j’s size
if (isize < jsize) {
// Then move i under j
Parent[irep] = jrep;
// Increment j's size by i's size
Size[jrep] += Size[irep];
}
// Else if j’s size is less than i’s size
else {
// Then move j under i
Parent[jrep] = irep;
// Increment i's size by j's size
Size[irep] += Size[jrep];
}
}
};
int main() {
int n = 5;
UnionFind unionFind(n);
unionFind.unionBySize(0, 1);
unionFind.unionBySize(2, 3);
unionFind.unionBySize(0, 4);
for (int i = 0; i < n; i++) {
cout << "Element " << i << ": Representative = "
<< unionFind.find(i) << endl;
}
return 0;
}
Java
// Java program for Union by Size with Path
// Compression
import java.util.Arrays;
class UnionFind {
private int[] Parent;
private int[] Size;
public UnionFind(int n)
{
// Initialize Parent array
Parent = new int[n];
for (int i = 0; i < n; i++) {
Parent[i] = i;
}
// Initialize Size array with 1s
Size = new int[n];
Arrays.fill(Size, 1);
}
// Function to find the representative (or the root
// node) for the set that includes i
public int find(int i) {
int root = Parent[i];
if (Parent[root] != root) {
return Parent[i] = find(root);
}
return root;
}
// Unites the set that includes i and the set that
// includes j by size
public void unionBySize(int i, int j)
{
// Find the representatives (or the root nodes) for
// the set that includes i
int irep = find(i);
// And do the same for the set that includes j
int jrep = find(j);
// Elements are in the same set, no need to unite
// anything.
if (irep == jrep)
return;
// Get the size of i’s tree
int isize = Size[irep];
// Get the size of j’s tree
int jsize = Size[jrep];
// If i’s size is less than j’s size
if (isize < jsize) {
// Then move i under j
Parent[irep] = jrep;
// Increment j's size by i's size
Size[jrep] += Size[irep];
}
// Else if j’s size is less than i’s size
else {
// Then move j under i
Parent[jrep] = irep;
// Increment i's size by j's size
Size[irep] += Size[jrep];
}
}
}
public class GFG {
public static void main(String[] args)
{
// Example usage
int n = 5;
UnionFind unionFind = new UnionFind(n);
// Perform union operations
unionFind.unionBySize(0, 1);
unionFind.unionBySize(2, 3);
unionFind.unionBySize(0, 4);
// Print the representative of each element after
// unions
for (int i = 0; i < n; i++) {
System.out.println("Element " + i
+ ": Representative = "
+ unionFind.find(i));
}
}
}
Python
class UnionFind:
def __init__(self, n):
self.Parent = list(range(n))
self.Size = [1] * n
# Function to find the representative (or the root
# node) for the set that includes i
def find(self, i):
root = self.Parent[i]
if self.Parent[root] != root:
self.Parent[i] = self.find(root)
return self.Parent[i]
return root
# Unites the set that includes i and the set that
# includes j by size
def unionBySize(self, i, j):
# Find the representatives (or the root nodes) for
# the set that includes i
irep = self.find(i)
# And do the same for the set that includes j
jrep = self.find(j)
# Elements are in the same set, no need to unite
# anything.
if irep == jrep:
return
# Get the size of i’s tree
isize = self.Size[irep]
# Get the size of j’s tree
jsize = self.Size[jrep]
# If i’s size is less than j’s size
if isize < jsize:
# Then move i under j
self.Parent[irep] = jrep
# Increment j's size by i's size
self.Size[jrep] += self.Size[irep]
# Else if j’s size is less than i’s size
else:
# Then move j under i
self.Parent[jrep] = irep
# Increment i's size by j's size
self.Size[irep] += self.Size[jrep]
n = 5
unionFind = UnionFind(n)
unionFind.unionBySize(0, 1)
unionFind.unionBySize(2, 3)
unionFind.unionBySize(0, 4)
for i in range(n):
print(f'Element {i}: Representative = {unionFind.find(i)}')
C#
// C# program for Union by Size with Path Compression
using System;
using System.Linq;
class UnionFind
{
private int[] Parent;
private int[] Size;
public UnionFind(int n)
{
// Initialize Parent array
Parent = new int[n];
for (int i = 0; i < n; i++) {
Parent[i] = i;
}
// Initialize Size array with 1s
Size = new int[n];
Array.Fill(Size, 1);
}
// Function to find the representative (or
// the root node) for the set that includes i
public int Find(int i) {
int root = Parent[i];
if (Parent[root] != root) {
return Parent[i] = Find(root);
}
return root;
}
// Unites the set that includes i and the set
// that includes j by size
public void UnionBySize(int i, int j)
{
// Find the representatives (or the root nodes)
// for the set that includes i
int irep = Find(i);
// And do the same for the set that includes j
int jrep = Find(j);
// Elements are in the same set, no need to unite anything.
if (irep == jrep)
return;
// Get the size of i’s tree
int isize = Size[irep];
// Get the size of j’s tree
int jsize = Size[jrep];
// If i’s size is less than j’s size
if (isize < jsize)
{
// Then move i under j
Parent[irep] = jrep;
// Increment j's size by i's size
Size[jrep] += Size[irep];
}
// Else if j’s size is less than i’s size
else
{
// Then move j under i
Parent[jrep] = irep;
// Increment i's size by j's size
Size[irep] += Size[jrep];
}
}
}
class GFG
{
public static void Main(string[] args)
{
int n = 5;
UnionFind unionFind = new UnionFind(n);
unionFind.UnionBySize(0, 1);
unionFind.UnionBySize(2, 3);
unionFind.UnionBySize(0, 4);
// Print the representative of each element after unions
for (int i = 0; i < n; i++)
{
Console.WriteLine("Element " + i + ": Representative = "
+ unionFind.Find(i));
}
}
}
JavaScript
class UnionFind {
constructor(n) {
this.Parent = Array.from({ length: n }, (_, i) => i);
this.Size = Array(n).fill(1);
}
// Function to find the representative (or the root
// node) for the set that includes i
find(i) {
let root = this.Parent[i];
if (this.Parent[root] !== root) {
return this.Parent[i] = this.find(root);
}
return root;
}
// Unites the set that includes i and the set that
// includes j by size
unionBySize(i, j) {
// Find the representatives (or the root nodes) for
// the set that includes i
const irep = this.find(i);
// And do the same for the set that includes j
const jrep = this.find(j);
// Elements are in the same set, no need to unite
// anything.
if (irep === jrep) return;
// Get the size of i’s tree
const isize = this.Size[irep];
// Get the size of j’s tree
const jsize = this.Size[jrep];
// If i’s size is less than j’s size
if (isize < jsize) {
// Then move i under j
this.Parent[irep] = jrep;
// Increment j's size by i's size
this.Size[jrep] += this.Size[irep];
} else {
// Then move j under i
this.Parent[jrep] = irep;
// Increment i's size by j's size
this.Size[irep] += this.Size[jrep];
}
}
}
const n = 5;
const unionFind = new UnionFind(n);
unionFind.unionBySize(0, 1);
unionFind.unionBySize(2, 3);
unionFind.unionBySize(0, 4);
for (let i = 0; i < n; i++) {
console.log(`Element ${i}: Representative = ${unionFind.find(i)}`);
}
OutputElement 0: Representative = 0
Element 1: Representative = 0
Element 2: Representative = 2
Element 3: Representative = 2
Element 4: Representative = 0
Disjoint Set Introduction
Find and Union Operation on Disjoint Sets
Union by Rank (Union-Find Algorithm)
Path Compression in Union-Find Algorithm
Similar Reads
Basics & Prerequisites
Data Structures
Array Data StructureIn this article, we introduce array, implementation in different popular languages, its basic operations and commonly seen problems / interview questions. An array stores items (in case of C/C++ and Java Primitive Arrays) or their references (in case of Python, JS, Java Non-Primitive) at contiguous
3 min read
String in Data StructureA string is a sequence of characters. The following facts make string an interesting data structure.Small set of elements. Unlike normal array, strings typically have smaller set of items. For example, lowercase English alphabet has only 26 characters. ASCII has only 256 characters.Strings are immut
2 min read
Hashing in Data StructureHashing is a technique used in data structures that efficiently stores and retrieves data in a way that allows for quick access. Hashing involves mapping data to a specific index in a hash table (an array of items) using a hash function. It enables fast retrieval of information based on its key. The
2 min read
Linked List Data StructureA linked list is a fundamental data structure in computer science. It mainly allows efficient insertion and deletion operations compared to arrays. Like arrays, it is also used to implement other data structures like stack, queue and deque. Hereâs the comparison of Linked List vs Arrays Linked List:
2 min read
Stack Data StructureA Stack is a linear data structure that follows a particular order in which the operations are performed. The order may be LIFO(Last In First Out) or FILO(First In Last Out). LIFO implies that the element that is inserted last, comes out first and FILO implies that the element that is inserted first
2 min read
Queue Data StructureA Queue Data Structure is a fundamental concept in computer science used for storing and managing data in a specific order. It follows the principle of "First in, First out" (FIFO), where the first element added to the queue is the first one to be removed. It is used as a buffer in computer systems
2 min read
Tree Data StructureTree Data Structure is a non-linear data structure in which a collection of elements known as nodes are connected to each other via edges such that there exists exactly one path between any two nodes. Types of TreeBinary Tree : Every node has at most two childrenTernary Tree : Every node has at most
4 min read
Graph Data StructureGraph Data Structure is a collection of nodes connected by edges. It's used to represent relationships between different entities. If you are looking for topic-wise list of problems on different topics like DFS, BFS, Topological Sort, Shortest Path, etc., please refer to Graph Algorithms. Basics of
3 min read
Trie Data StructureThe Trie data structure is a tree-like structure used for storing a dynamic set of strings. It allows for efficient retrieval and storage of keys, making it highly effective in handling large datasets. Trie supports operations such as insertion, search, deletion of keys, and prefix searches. In this
15+ min read
Algorithms
Searching AlgorithmsSearching algorithms are essential tools in computer science used to locate specific items within a collection of data. In this tutorial, we are mainly going to focus upon searching in an array. When we search an item in an array, there are two most common algorithms used based on the type of input
2 min read
Sorting AlgorithmsA Sorting Algorithm is used to rearrange a given array or list of elements in an order. For example, a given array [10, 20, 5, 2] becomes [2, 5, 10, 20] after sorting in increasing order and becomes [20, 10, 5, 2] after sorting in decreasing order. There exist different sorting algorithms for differ
3 min read
Introduction to RecursionThe process in which a function calls itself directly or indirectly is called recursion and the corresponding function is called a recursive function. A recursive algorithm takes one step toward solution and then recursively call itself to further move. The algorithm stops once we reach the solution
14 min read
Greedy AlgorithmsGreedy algorithms are a class of algorithms that make locally optimal choices at each step with the hope of finding a global optimum solution. At every step of the algorithm, we make a choice that looks the best at the moment. To make the choice, we sometimes sort the array so that we can always get
3 min read
Graph AlgorithmsGraph is a non-linear data structure like tree data structure. The limitation of tree is, it can only represent hierarchical data. For situations where nodes or vertices are randomly connected with each other other, we use Graph. Example situations where we use graph data structure are, a social net
3 min read
Dynamic Programming or DPDynamic Programming is an algorithmic technique with the following properties.It is mainly an optimization over plain recursion. Wherever we see a recursive solution that has repeated calls for the same inputs, we can optimize it using Dynamic Programming. The idea is to simply store the results of
3 min read
Bitwise AlgorithmsBitwise algorithms in Data Structures and Algorithms (DSA) involve manipulating individual bits of binary representations of numbers to perform operations efficiently. These algorithms utilize bitwise operators like AND, OR, XOR, NOT, Left Shift, and Right Shift.BasicsIntroduction to Bitwise Algorit
4 min read
Advanced
Segment TreeSegment Tree is a data structure that allows efficient querying and updating of intervals or segments of an array. It is particularly useful for problems involving range queries, such as finding the sum, minimum, maximum, or any other operation over a specific range of elements in an array. The tree
3 min read
Pattern SearchingPattern searching algorithms are essential tools in computer science and data processing. These algorithms are designed to efficiently find a particular pattern within a larger set of data. Patten SearchingImportant Pattern Searching Algorithms:Naive String Matching : A Simple Algorithm that works i
2 min read
GeometryGeometry is a branch of mathematics that studies the properties, measurements, and relationships of points, lines, angles, surfaces, and solids. From basic lines and angles to complex structures, it helps us understand the world around us.Geometry for Students and BeginnersThis section covers key br
2 min read
Interview Preparation
Practice Problem