# Disjoint Set Data Structures

• Difficulty Level : Medium
• Last Updated : 07 Jun, 2022

Consider a situation with a number of persons and following tasks to be performed on them.

1. Add a new friendship relation, i.e., a person x becomes friend of another person y.
2. Find whether individual x is a friend of individual y (direct or indirect friend)

Example:

```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

And 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}```

Problem : To find whether x and y belong to same group or not, i.e., to find if x and y are direct/indirect friends.
Solution : Partitioning the individuals into different sets according to the groups in which they fall. This method is known as disjoint set data structure which maintains collection of disjoint sets and each set is represented by its representative which is one of its members.

Approach:

• How to Resolve sets ? Initially all elements belong to different sets. After working on the given relations, we select a member as representative. There can be many ways to select a representative, a simple one is to select with the biggest index.
• Check if 2 persons are in the same group ? If representatives of two individuals are same, then they’ll become friends.

Data Structures used:
Array : An array of integers, 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 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 :

Find : Can be implemented by recursively traversing the parent array until we hit a node who is parent of itself.

```// Finds the representative of the set
// that i is an element of
int find(int i)
{
// If i is the parent of itself
if (parent[i] == i)
{
// Then i is the representative of
// this set
return i;
}
else
{
// Else if i is not the parent of
// itself, then i is not the
// representative of his set. So we
// recursively call Find on its parent
return find(parent[i]);
}
}```

Union: It takes, as input, two elements. 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, effectively merging the trees and the sets.

```// Unites the set that includes i
// and the set that includes j
void union(int i, int j)
{
// Find the representatives
// (or the root nodes) for the set
// that includes i

int irep = this.Find(i),

// And do the same for the set
// that includes j
int jrep = this.Find(j);

// Make the parent of iâ€™s representative
// be jâ€™s  representative effectively
// moving all of iâ€™s set into jâ€™s set)
this.Parent[irep] = jrep;
}```

Improvements (Union by Rank and Path Compression)
The efficiency depends heavily on the height of the tree. We need to minimize the height of tree in order to improve the efficiency. We can use Path Compression and Union by rank methods to do so.

Path Compression (Modifications to find()) : 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:

```// Finds the representative of the set that i
// is an element of.
int find(int i)
{
// If i is the parent of itself
if (Parent[i] == i)
{
// Then i is the representative
return i;
}
else
{
// Recursively find the representative.
int result = find(Parent[i]);

// We cache the result by moving iâ€™s node
// directly under the representative of this
// set
Parent[i] = result;

// And then we return the result
return result;
}
}```

Union by Rank: First of all, we need a new array of integers called rank[]. Size of this array is same as the parent array. If i is a representative of a set, rank[i] is the height of the tree representing the set.
Now recall that, in the Union operation, it doesnâ€™t matter which of the two trees is moved under the other (see last two image examples above). 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.

```// Unites the set that includes i and the set
// that includes j
void union(int i, int j)
{
// Find the representatives (or the root nodes)
// for the set that includes i
int irep = this.find(i);

// And do the same for the set that includes j
int jrep = this.Find(j);

// Elements are in same set, no need to
// unite anything.
if (irep == jrep)
return;

// Get the rank of iâ€™s tree
irank = Rank[irep],

// Get the rank of jâ€™s tree
jrank = Rank[jrep];

// If iâ€™s rank is less than jâ€™s rank
if (irank < jrank)
{
// Then move i under j
this.parent[irep] = jrep;
}

// Else if jâ€™s rank is less than iâ€™s rank
else if (jrank < irank)
{
// Then move j under i
this.Parent[jrep] = irep;
}

// Else if their ranks are the same
else
{

// Then move i under j (doesnâ€™t matter
// which one goes where)
this.Parent[irep] = jrep;

// And increment the result treeâ€™s
// rank by 1
Rank[jrep]++;
}
}```

## C++

 `// C++ implementation of disjoint set``#include ``using` `namespace` `std;``class` `DisjSet {``    ``int` `*rank, *parent, n;` `public``:``    ``// Constructor to create and``    ``// initialize sets of n items``    ``DisjSet(``int` `n)``    ``{``        ``rank = ``new` `int``[n];``        ``parent = ``new` `int``[n];``        ``this``->n = n;``        ``makeSet();``    ``}` `    ``// Creates n single item sets``    ``void` `makeSet()``    ``{``        ``for` `(``int` `i = 0; i < n; i++) {``            ``parent[i] = i;``        ``}``    ``}` `    ``// Finds set of given item x``    ``int` `find(``int` `x)``    ``{``        ``// Finds the representative of the set``        ``// that x is an element of``        ``if` `(parent[x] != x) {` `            ``// if x is not the parent of itself``            ``// Then x is not the representative of``            ``// his set,``            ``parent[x] = find(parent[x]);` `            ``// so we recursively call Find on its parent``            ``// and move i's node directly under the``            ``// representative of this set``        ``}` `        ``return` `parent[x];``    ``}` `    ``// Do union of two sets represented``    ``// by x and y.``    ``void` `Union(``int` `x, ``int` `y)``    ``{``        ``// Find current sets of x and y``        ``int` `xset = find(x);``        ``int` `yset = find(y);` `        ``// If they are already in same set``        ``if` `(xset == yset)``            ``return``;` `        ``// Put smaller ranked item under``        ``// bigger ranked item if ranks are``        ``// different``        ``if` `(rank[xset] < rank[yset]) {``            ``parent[xset] = yset;``        ``}``        ``else` `if` `(rank[xset] > rank[yset]) {``            ``parent[yset] = xset;``        ``}` `        ``// If ranks are same, then increment``        ``// rank.``        ``else` `{``            ``parent[yset] = xset;``            ``rank[xset] = rank[xset] + 1;``        ``}``    ``}``};` `int` `main()``{``    ``DisjSet obj(5);``    ``obj.Union(0, 2);``    ``obj.Union(4, 2);``    ``obj.Union(3, 1);``    ``if` `(obj.find(4) == obj.find(0))``        ``cout << ``"Yes\n"``;``    ``else``        ``cout << ``"No\n"``;``    ``if` `(obj.find(1) == obj.find(0))``        ``cout << ``"Yes\n"``;``    ``else``        ``cout << ``"No\n"``;` `    ``return` `0;``}`

## Java

 `// A Java program to implement Disjoint Set Data``// Structure.``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;``        ``makeSet();``    ``}` `    ``// Creates n sets with single item in each``    ``void` `makeSet()``    ``{``        ``for` `(``int` `i = ``0``; i < n; i++) {``            ``// Initially, all elements are in``            ``// their own set.``            ``parent[i] = i;``        ``}``    ``}` `    ``// Returns representative of x's set``    ``int` `find(``int` `x)``    ``{``        ``// Finds the representative of the set``        ``// that x is an element of``        ``if` `(parent[x] != x) {``            ``// if x is not the parent of itself``            ``// Then x is not the representative of``            ``// his set,``            ``parent[x] = find(parent[x]);` `            ``// so we recursively call Find on its parent``            ``// and move i's node directly under the``            ``// representative of this set``        ``}` `        ``return` `parent[x];``    ``}` `    ``// 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"``);``    ``}``}`

## Python3

 `# Python3 program to implement Disjoint Set Data``# Structure.` `class` `DisjSet:``    ``def` `__init__(``self``, n):``        ``# Constructor to create and``        ``# initialize sets of n items``        ``self``.rank ``=` `[``1``] ``*` `n``        ``self``.parent ``=` `[i ``for` `i ``in` `range``(n)]`  `    ``# Finds set of given item x``    ``def` `find(``self``, x):``        ` `        ``# Finds the representative of the set``        ``# that x is an element of``        ``if` `(``self``.parent[x] !``=` `x):``            ` `            ``# if x is not the parent of itself``            ``# Then x is not the representative of``            ``# its set,``            ``self``.parent[x] ``=` `self``.find(``self``.parent[x])``            ` `            ``# so we recursively call Find on its parent``            ``# and move i's node directly under the``            ``# representative of this set` `        ``return` `self``.parent[x]`  `    ``# Do union of two sets represented``    ``# by x and y.``    ``def` `Union(``self``, x, y):``        ` `        ``# Find current sets of x and y``        ``xset ``=` `self``.find(x)``        ``yset ``=` `self``.find(y)` `        ``# If they are already in same set``        ``if` `xset ``=``=` `yset:``            ``return` `        ``# Put smaller ranked item under``        ``# bigger ranked item if ranks are``        ``# different``        ``if` `self``.rank[xset] < ``self``.rank[yset]:``            ``self``.parent[xset] ``=` `yset` `        ``else` `if` `self``.rank[xset] > ``self``.rank[yset]:``            ``self``.parent[yset] ``=` `xset` `        ``# If ranks are same, then move y under``        ``# x (doesn't matter which one goes where)``        ``# and increment rank of x's tree``        ``else``:``            ``self``.parent[yset] ``=` `xset``            ``self``.rank[xset] ``=` `self``.rank[xset] ``+` `1` `# Driver code``obj ``=` `DisjSet(``5``)``obj.Union(``0``, ``2``)``obj.Union(``4``, ``2``)``obj.Union(``3``, ``1``)``if` `obj.find(``4``) ``=``=` `obj.find(``0``):``    ``print``(``'Yes'``)``else``:``    ``print``(``'No'``)``if` `obj.find(``1``) ``=``=` `obj.find(``0``):``    ``print``(``'Yes'``)``else``:``    ``print``(``'No'``)` `# This code is contributed by ng24_7.`

## C#

 `// A C# program to implement ``// Disjoint Set Data Structure.``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;``        ``makeSet();``    ``}` `    ``// Creates n sets with single item in each``    ``public` `void` `makeSet()``    ``{``        ``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` `x)``    ``{``        ``// Finds the representative of the set``        ``// that x is an element of``        ``if` `(parent[x] != x)``        ``{``            ` `            ``// if x is not the parent of itself``            ``// Then x is not the representative of``            ``// his set,``            ``parent[x] = find(parent[x]);` `            ``// so we recursively call Find on its parent``            ``// and move i's node directly under the``            ``// representative of this set``        ``}``        ``return` `parent[x];``    ``}` `    ``// Unites the set that includes x and``    ``// the set that includes x``    ``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` `GFG``{``    ``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))``            ``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"``);``    ``}``}` `// This code is contributed by Rajput-Ji`

Output:

```Yes
No```

Applications :

Try to solve this problem and check how much you learnt and do comment on the complexity of the given question.
This article is contributed by Nikhil Tekwani. If you like GeeksforGeeks and would like to contribute, you can also write an article and mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.