mirror of
https://github.com/dholerobin/Lecture_Notes.git
synced 2025-07-01 13:06:29 +00:00
Update DSU.md
This commit is contained in:
parent
3e5a5aebed
commit
d852b963bf
@ -3,37 +3,38 @@
|
||||
|
||||
Disjoint Set Union is one of the simplest and easy to implement data structure, which is used to keep track of disjoint(Non-overlapping) dynamic sets.
|
||||
|
||||

|
||||

|
||||
|
||||
In the image above, $\{a,b,c,d\}$ and $\{e,f\}$ are two non-overlapping sets. Dynamic here says that we can combine any two sets and still keep track of elements of it.
|
||||
In the image above, $\{a,b,c,d\}$ and $\{e,f\}$ are two non-overlapping(disjoint) sets. Dynamic here means that we can combine any two sets, so they are dynamic.
|
||||
|
||||
**Note:** Here disjoint set is represented as a tree and terminology of tree is used.
|
||||
|
||||
There are three main operations of this data structure: Make-set, Find and Union
|
||||
|
||||
1. **Make-Set**: This operation creates a disjoint set each one having a single element.
|
||||
1. **Make-Set**: This operation creates a disjoint set having a single element.
|
||||
|
||||
2. **Find**: This operation finds a unique set to which a particular element belongs.
|
||||
|
||||
3. **Union**: This operation unifies two disjoint sets.
|
||||
|
||||
There are many ways we can represent this data structure: Linked list, Array, Trees. But here we will discuss its representation using array and visualize using tree.
|
||||
There are many ways we can implement this data structure: Linked list, Array, Trees. But here we will implement using array and represent using tree.
|
||||
|
||||
**Some Terminologies**
|
||||
|
||||
- **Parent** is a main attribute of an element which represents an element by which a particular element is connected with some disjoint set.
|
||||
|
||||

|
||||
In the image below, $c$ is parent of $d$ and $a$ is parent of $c$.
|
||||
|
||||

|
||||
|
||||
In the image, $c$ is parent of $d$ and $a$ is parent of $c$.
|
||||
|
||||
- **Root** is an element of a set whose parent is itself. It is unique per set. $a$ is the root element for the left disjoint set.
|
||||
|
||||
- **Root** is an element of a set whose parent is itself. It is unique per set.
|
||||
$a$ is the root element for the left disjoint set.
|
||||
|
||||
|
||||
## Operation Make-Set
|
||||
|
||||
Make-Set operation creates a new set having a single element (means $size=1$) which is having a unique id.
|
||||
|
||||
**Pseudocode:**
|
||||
```
|
||||
MAKE-SET(x)
|
||||
{
|
||||
@ -43,6 +44,9 @@ MAKE-SET(x)
|
||||
```
|
||||
Here X is the only element in the set so it is parent of itself.
|
||||
|
||||
The image below represents sets generated by this operation. Where each one having arrow coming to itself, which represents that it is its own parent right now. Each one have size of 1.
|
||||

|
||||
|
||||
We are working with arrays, so the code to make $n$ sets is as below:
|
||||
|
||||
```c++
|
||||
@ -63,9 +67,11 @@ void Make_sets(int n)
|
||||
|
||||
## Operation Find
|
||||
|
||||
$Find(X)$ basically finds the root element of the disjoint set to which $X$ belongs.
|
||||
$\text{Find}(X)$ basically finds the root element of the disjoint set to which $X$ belongs.
|
||||
|
||||
IMAGE
|
||||
If we apply $\text{Find}(d)$ or $\text{Find}(c)$ operation for the set in the image below, then it will return '$a$' which is a root element.
|
||||
|
||||

|
||||
|
||||
Here the thing to note is that, the root element of a root element of any disjoint set is itself i.e., $root.parent = root$
|
||||
|
||||
@ -73,6 +79,7 @@ Here the thing to note is that, the root element of a root element of any disjoi
|
||||
|
||||
Until you reach at the root element, traverse the tree of the disjoint set upwards.
|
||||
|
||||
**Pseudocode:**
|
||||
```
|
||||
FIND(X)
|
||||
while x != x.parent
|
||||
@ -81,6 +88,7 @@ FIND(X)
|
||||
return x;
|
||||
```
|
||||
**Visualization**
|
||||

|
||||
|
||||
---------------
|
||||
### Quiz Time
|
||||
@ -118,15 +126,18 @@ int Find(x)
|
||||
```
|
||||
**Time Complexity:** This operation can take $O(N)$ in worst case where N is the size of the set-which can be number of total elements at maximum.
|
||||
|
||||
This is too much. Right? What can we do?
|
||||
This is too much. Right? What else can we do?
|
||||
|
||||
We have a technique named **"Path compression"**, which burns this time to $O(logN)$ on average. Note the term **on average**.
|
||||
We have a technique named **"Path compression"**, which burns this time to $O(log^*N)$. $log^*N$ is iterated logarithm-number of time you have to apply $log$ to $N$ before the result is less than or equal to 1.
|
||||
|
||||
The idea of the Path compression is: **It re-connects every vertex to the root vertex directly rather than by a path**.
|
||||
|
||||
Image
|
||||
If we apply $\text{Find}(d)$ operation with the path compression, then the following thing will happen.
|
||||

|
||||
|
||||
How can we do it? It is easy, we just need a little modification in $Find(X)$.
|
||||
How can we do it? It is easy, we just need a little modification in $\text{Find}(X)$.
|
||||
|
||||
**Pseudocode:**
|
||||
```
|
||||
FIND(x)
|
||||
if x == x.parent
|
||||
@ -135,7 +146,7 @@ FIND(x)
|
||||
x.parent = FIND(x.parent);
|
||||
return x.parent
|
||||
```
|
||||
So every time we run this function, it will re-connect every vertex on the path to the root, directly to root.
|
||||
So every time we run this function, it will re-connect every vertex on the path to the root, directly to the root.
|
||||
|
||||
---
|
||||
### Quiz Time
|
||||
@ -190,6 +201,7 @@ int Find(x)
|
||||
```
|
||||
|
||||
## Operation Union
|
||||
|
||||
$Union(X,Y)$ operation first of all finds root element of both the disjoint sets containing X and Y respectively. Then it connects the root element of one of the disjoint set to the another.
|
||||
|
||||
Well, how do we decide which root will connet to which? If we do it randomly then it may increase the tree height up to O(N), which means that the next $Find(x)$ operation will take O(N) time. Can we do better?
|
||||
@ -199,6 +211,11 @@ Yes, we have two standard techniques: **By size and By rank**.
|
||||
### By Size
|
||||
Union by size technique decides it based on the sizes of the sets. Everytime, the smaller size set is attatched to the larger size set.
|
||||
|
||||

|
||||
|
||||
**Note:** The numbers in square bracket represents the size of the set below it.
|
||||
|
||||
**Pseudocode:**
|
||||
```
|
||||
UNION(X,Y)
|
||||
Rx = FIND(X), Ry = FIND(Y)
|
||||
@ -218,6 +235,15 @@ In Union by rank technique, shorter tree is attatched to taller tree. Initally r
|
||||
|
||||
If both sets have same rank, then the resulting rank will be one greater. Otherwise the resulting rank will be larger of the two.
|
||||
|
||||
**Note:** In the image below, the numbers in square bracket represents the rank of the set below it.
|
||||
|
||||
Example 1:
|
||||
|
||||

|
||||
Example 2:
|
||||

|
||||
|
||||
**Pseudocode:**
|
||||
```
|
||||
UNION(X,Y)
|
||||
Rx = FIND(X), Ry = FIND(Y)
|
||||
@ -271,10 +297,10 @@ void union(int x,int y)
|
||||
}
|
||||
```
|
||||
|
||||
**Time Complexity of Union**
|
||||
### Time Complexity of Union
|
||||
|
||||
1. Without path compression: $O(N)$
|
||||
2. With path compression: $O(logN)$ on an average
|
||||
2. With path compression: $O(log^*N)$
|
||||
|
||||
## Applications of DSU
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user