struct UnionFind {
parent: Vec<usize>,
}
impl UnionFind {
fn new(size: usize) -> Self {
Self { parent: (0..size).collect() }
}
fn find(&mut self, x: usize) -> usize {
if self.parent[x] != x {
self.parent[x] = self.find(self.parent[x]);
}
self.parent[x]
}
fn union(&mut self, x: usize, y: usize) {
let px = self.find(x);
let py = self.find(y);
if px != py {
self.parent[py] = px;
}
}
}
fn main() {
let mut uf = UnionFind::new(5);
uf.union(0, 1);
uf.union(1, 2);
uf.union(3, 4);
println!("{:?}", uf.parent);
}After union(0,1), parent of 1 becomes 0. After union(1,2), parent of 2 becomes 0 (since 1's parent is 0). After union(3,4), parent of 4 becomes 3. So the parent array is [0,0,0,3,3].
struct UnionFind {
parent: Vec<usize>,
}
impl UnionFind {
fn find(&mut self, x: usize) -> usize {
if self.parent[x] != x {
self.parent[x] = self.find(self.parent[x]);
}
self.parent[x]
}
}
fn main() {
let mut uf = UnionFind { parent: vec![0, 0, 1, 3, 3] };
uf.find(2);
println!("{:?}", uf.parent);
}Initially, parent[2] = 1, and parent[1] = 0. Calling find(2) updates parent[2] directly to 0, the root. So the array becomes [0, 0, 0, 3, 3].
struct UnionFind {
parent: Vec<usize>,
rank: Vec<usize>,
}
impl UnionFind {
fn new(size: usize) -> Self {
Self {
parent: (0..size).collect(),
rank: vec![0; size],
}
}
fn find(&mut self, x: usize) -> usize {
if self.parent[x] != x {
self.parent[x] = self.find(self.parent[x]);
}
self.parent[x]
}
fn union(&mut self, x: usize, y: usize) {
let px = self.find(x);
let py = self.find(y);
if px != py {
if self.rank[px] < self.rank[py] {
self.parent[px] = py;
} else if self.rank[px] > self.rank[py] {
self.parent[py] = px;
} else {
self.parent[py] = px;
self.rank[px] += 1;
}
}
}
}
fn main() {
let mut uf = UnionFind::new(4);
uf.union(0, 1);
uf.union(2, 3);
uf.union(1, 3);
println!("parent: {:?}", uf.parent);
println!("rank: {:?}", uf.rank);
}After union(0,1), parent[1]=0, rank[0]=1. After union(2,3), parent[3]=2, rank[2]=1. After union(1,3), roots are 0 and 2 with rank 1 each, so attach 2 under 0 and increment rank[0] to 2. But since ranks were equal, rank[0] increments by 1. So parent array becomes [0,0,0,2] (because 2's parent is set to 0), rank array is [1,0,0,0].
struct UnionFind {
parent: Vec<usize>,
}
impl UnionFind {
fn new(size: usize) -> Self {
Self { parent: (0..size).collect() }
}
fn find(&mut self, x: usize) -> usize {
if self.parent[x] != x {
self.find(self.parent[x])
} else {
x
}
}
fn union(&mut self, x: usize, y: usize) {
let px = self.find(x);
let py = self.find(y);
if px != py {
self.parent[py] = px;
}
}
}
fn main() {
let mut uf = UnionFind::new(2);
uf.union(0, 1);
uf.union(0, 1);
println!("{:?}", uf.parent);
}The find function calls itself recursively but does not update parent[x] or return the recursive call's result properly, causing infinite recursion and stack overflow.
struct UnionFind {
parent: Vec<usize>,
}
impl UnionFind {
fn new(size: usize) -> Self {
Self { parent: (0..size).collect() }
}
fn find(&mut self, x: usize) -> usize {
if self.parent[x] != x {
self.parent[x] = self.find(self.parent[x]);
}
self.parent[x]
}
fn union(&mut self, x: usize, y: usize) {
let px = self.find(x);
let py = self.find(y);
if px != py {
self.parent[py] = px;
}
}
fn count_components(&mut self) -> usize {
let mut roots = std::collections::HashSet::new();
for i in 0..self.parent.len() {
roots.insert(self.find(i));
}
roots.len()
}
}
fn main() {
let mut uf = UnionFind::new(7);
uf.union(0, 1);
uf.union(1, 2);
uf.union(3, 4);
uf.union(5, 6);
println!("{}", uf.count_components());
}Unions form groups: {0,1,2}, {3,4}, {5,6}, so total groups are 3. Element 7 does not exist, so total components are 3.
