Union-Find Algorithm


1. Dynamic Connectivity Problem

Example:

2. UF (Union-Find) Interface

public interface UF
{
    public int find(int p);          // returns site p's component/group id
    public boolean connected(int p, int q); // returns true if p and q are connected
    public void union(int p, int q); // adds connection between p and q
    public int count();              // returns number of components
}

Representation of site-components using an array (named 'id').

        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
  id  | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
      +---+---+---+---+---+---+---+---+ 

3. Approach #1: Quick-Find

 public void union(int p, int q)
{
  int pcomp = find(p);
  int qcomp = find(q);
        
  if(pcomp == qcomp) {
    return;
  }
  components--;
  for(int i = 0; i < n; i++) {
    if (id[i] == pcomp) {
      id[i] = qcomp;
    }
  }
}
Initial 
        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
  id  | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
      +---+---+---+---+---+---+---+---+ 
union(0,1)
      +---+---+---+---+---+---+---+---+
  id  | 1 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
      +---+---+---+---+---+---+---+---+ 
union(0,3)
      +---+---+---+---+---+---+---+---+
  id  | 3 | 3 | 2 | 3 | 4 | 5 | 6 | 7 |
      +---+---+---+---+---+---+---+---+ 
connected(0,3)  => true 
union(4,5)
        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
  id  | 3 | 3 | 2 | 3 | 5 | 5 | 6 | 7 |
      +---+---+---+---+---+---+---+---+ 
union(0,4)
        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
  id  | 5 | 5 | 2 | 5 | 5 | 5 | 6 | 7 |
      +---+---+---+---+---+---+---+---+ 
union(2,7)
        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
  id  | 5 | 5 | 7 | 5 | 5 | 5 | 6 | 7 |
      +---+---+---+---+---+---+---+---+ 
connected(2,3) => false

But the complexity is not so good. Order of growth of union(p,q) is n if p and q are not connected.

EXERCISE: [Textbook Exercise #1.5.1 (p.  235)] Show the contents of the id[] array and the number of times the array is accessed for each input pair when you use quick-find for the sequence 9-0, 3-4, 5-8, 7-2, 2-1, 5-7, 0-3, 4-2.


4. Approach #2: Quick-Union

Conceptually this scheme is easier to understand if we think of a tree model:

Initial 
        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
  id  | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
      +---+---+---+---+---+---+---+---+ 
union(0,1)
      +---+---+---+---+---+---+---+---+
  id  | 1 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
      +---+---+---+---+---+---+---+---+ 
union(0,3)
      +---+---+---+---+---+---+---+---+
  id  | 1 | 3 | 2 | 3 | 4 | 5 | 6 | 7 |
      +---+---+---+---+---+---+---+---+ 
connected(0,3)  => true 
union(4,5)
        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
  id  | 1 | 3 | 2 | 3 | 5 | 5 | 6 | 7 |
      +---+---+---+---+---+---+---+---+ 
union(0,4)
        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
  id  | 1 | 3 | 2 | 5 | 5 | 5 | 6 | 7 |
      +---+---+---+---+---+---+---+---+ 
union(2,7)
        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
  id  | 1 | 3 | 7 | 5 | 5 | 5 | 6 | 7 |
      +---+---+---+---+---+---+---+---+ 
connected(2,3) => false
EXERCISE: [Textbook Exercise #1.5.2 (p.  235)] Do the previous question, but use quick-union.  In addition, draw the forest of trees represented by the ad[] array after each input pair is processed.

5. Approach #4: Weighted Union


6. Approach #5: Weighted Union with Path Compression

     4 (height 0)          8  (height 1)
                          /|\ 
                         3 9 5

For example, with components:

      0         1           5  
      |         |           |  
    +---+     +---+       +---+
    |   |     |   |       |   |
    2   6     3   4       7   8
        |                      
        9                        

excute union(9,8)  

Then

1. p = 9 and q = 8

2. pcomp = 0 and qcomp = 5

3. make 0 be a child of 5      

4. make sites p to pcomp be a children of qcomp: make 9 and 6 be
   children of 5
    

So first (after step 3) of union(9,8) we get

   0         1           5               1               5
   |         |           |               |               |    
 +---+     +---+       +---+    =>     +---+         +---+---+
 |   |     |   |       |   |           |   |         |   |   |
 2   6     3   4       7   8           3   4         0   7   8
     |                                               |         
     9                                             +---+       
                                                   |   |       
                                                   2   6       
                                                       |       
                                                       9      

Then after path compression,

           1                    5
           |                    |
 =>      +---+              +-+-+-+-+
         |   |              | | | | |
         3   4              0 9 6 7 8
                            |  
                            2   

After this compression, the loop in find(p) will execute only once for p = 0, 6, 9 as well as 7 and 8.