QuickUnion

A near-constant time solution to dynamic connectivity using weighted trees and path compression.


Context

QuickUnion is a significantly improved version of Quick-Find, addressing its inefficiencies by representing components as trees rather than flat labels.

Two optimizations make it fast in practice:

Combined, these techniques dramatically reduce tree height and make connectivity operations almost constant time in practice.


Core idea


Implementation

import java.util.Arrays;

public class QuickUnion {
    private final int[] data;
    private final int[] sizes;
    private int count;
    
    public QuickUnion(int n) {
        data = new int[n];
        sizes = new int[n];
        for (var i = 0; i < n; i++) {
            data[i] = i;
            sizes[i] = 1;
        }
        count = n;   
    }
    
    public int size() { return count; }
    
    public boolean isConnected(int p, int q) {
        return root(p) == root(q);
    }
    
    public int find(int p) { return root(p); }
    
    public void connect(int p, int q) {
        var cmpP = root(p);
        var cmpQ = root(q);
        
        if (cmpP == cmpQ) return;
        
        if (sizes[cmpP] < sizes[cmpQ]) {
            data[cmpP] = cmpQ;
            sizes[cmpQ] += sizes[cmpP];
        } else {
            data[cmpQ] = cmpP;
            sizes[cmpP] += sizes[cmpQ];
        }
        
        count--;
    }
    
    private int root(int p) {
        while (p != data[p]) {
            data[p] = data[data[p]];
            p = data[p];
        }
        return p;
    }
    
    @Override
    public String toString() { return Arrays.toString(data); }
}