Disjoint Set Union (Union-Find) with Path Compression
Union-Find data structure with path compression and union by rank for near constant-time connectivity queries.
main.go
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
package main
import "fmt"
type DSU struct {
parent []int
rank []int
}
func NewDSU(n int) *DSU {
parent := make([]int, n)
rank := make([]int, n)
for i := 0; i < n; i++ {
parent[i] = i
}
return &DSU{parent: parent, rank: rank}
}
func (d *DSU) Find(x int) int {
if d.parent[x] != x {
d.parent[x] = d.Find(d.parent[x])
}
return d.parent[x]
}
func (d *DSU) Union(a, b int) bool {
ra, rb := d.Find(a), d.Find(b)
if ra == rb {
return false
}
if d.rank[ra] < d.rank[rb] {
ra, rb = rb, ra
}
d.parent[rb] = ra
if d.rank[ra] == d.rank[rb] {
d.rank[ra]++
}
return true
}
func (d *DSU) Connected(a, b int) bool {
return d.Find(a) == d.Find(b)
}
func main() {
d := NewDSU(6)
d.Union(0, 1)
d.Union(2, 3)
d.Union(1, 2)
fmt.Println("0 connected to 3?", d.Connected(0, 3))
fmt.Println("4 connected to 5?", d.Connected(4, 5))
}How It Works
Union-Find data structure with path compression and union by rank for near constant-time connectivity queries.
Initializes each node as its own parent; Find flattens the tree via path compression; Union merges roots based on rank to keep trees shallow; supports connected queries for any two nodes.
Key Concepts
- 1Path compression drastically reduces future lookup depth.
- 2Union by rank keeps the forest balanced.
- 3Connected checks are O(1) after near-constant-time unions.
When to Use This Pattern
- Dynamic connectivity problems in graphs or networks.
- Kruskal's algorithm for minimum spanning tree construction.
- Grouping elements in clustering or percolation simulations.
Best Practices
- Reset or recreate the structure when the element set changes.
- Avoid using out-of-range node identifiers.
- Add tests for union and find invariants after mutations.
Go Version1.18+
Difficultybeginner
Production ReadyYes
Lines of Code53