并查集

TypeScript
export function useUnionFind(n: number) {
    const parent: number[] = new Array(n).fill(0).map((_, i) => i)
    const size: number[] = new Array(n).fill(1)

    function find(x: number) {
        if (parent[x] !== x) parent[x] = find(parent[x])

        return parent[x]
    }
    function union(x: number, y: number) {
        let rx = find(x)
        let ry = find(y)
        if (rx === ry) return false
        if (size[rx] > size[ry]) [rx, ry] = [ry, rx]

        parent[rx] = ry
        size[ry] += size[rx]
        return true
    }

    function isUnion(x: number, y: number) {
        return find(x) === find(y)
    }

    function setSize(x: number) {
        return size[find(x)]
    }

    return {
        union,
        find,
        isUnion,
        setSize,
    }
}
JavaScript
export function useUnionFind(n) {
    const parent = new Array(n).fill(0).map((_, i) => i)
    const size = new Array(n).fill(1)
    function find(x) {
        if (parent[x] !== x) parent[x] = find(parent[x])
        return parent[x]
    }
    function union(x, y) {
        let rx = find(x)
        let ry = find(y)
        if (rx === ry) return false
        if (size[rx] > size[ry]) [rx, ry] = [ry, rx]
        parent[rx] = ry
        size[ry] += size[rx]
        return true
    }
    function isUnion(x, y) {
        return find(x) === find(y)
    }
    function setSize(x) {
        return size[find(x)]
    }
    return {
        union,
        find,
        isUnion,
        setSize,
    }
}
Rust
pub struct UnionFind {
    parent: Vec<usize>,
    size: Vec<usize>,
    groups: usize,
}

impl UnionFind {
    pub fn new(n: usize) -> Self {
        let parent = (0..n).collect::<Vec<usize>>();
        let size = vec![1; n];
        Self {
            parent,
            size,
            groups: n,
        }
    }

    pub fn find(&mut self, x: usize) -> usize {
        if self.parent[x] != x {
            self.parent[x] = self.find(self.parent[x]);
        }
        self.parent[x]
    }

    pub fn union(&mut self, x: usize, y: usize) -> bool {
        let (mut rx, mut ry) = (self.find(x), self.find(y));
        if rx == ry {
            return false;
        }
        self.groups -= 1;
        if self.size[rx] > self.size[ry] {
            std::mem::swap(&mut rx, &mut ry);
        }
        self.parent[rx] = ry;
        self.size[ry] += self.size[rx];
        true
    }
}
Java

class UnionFind {

    int[] parent, size;

    public UnionFind(int n) {
        parent = new int[n];
        size = new int[n];
        for (int i = 0; i < n; i++) {
            parent[i] = i;
            size[i] = 1;
        }
    }

    /**
     * 合并两个节点所在的集合
     *
     * @param x 待合并的一个节点
     * @param y 待合并的另一个节点
     * @return null
     */
    public boolean union(int x, int y) {
        int rootX = find(x), rootY = find(y);
        if (rootX == rootY) { // 在同一个集合中
            return false;
        }
        if (size[rootX] > size[rootY]) { // 按秩合并,优化时间
            int t = rootX;
            rootX = rootY;
            rootY = t;
        }
        parent[rootX] = rootY;
        size[rootY] += size[rootX];
        return true;
    }

    public boolean isUnion(int x, int y) {
        return find(x) == find(y);
    }

    /**
     * 查找根节点
     *
     * @param x 待查找的节点
     * @return 返回根节点
     */
    private int find(int x) {
        if (parent[x] != x) {
            parent[x] = find(parent[x]); // 路径压缩
        }
        return parent[x];
    }
}
Go
package algo

type UnionFind struct {
    parent []int
    size   []int
    groups int
}

func NewUnionFind(n int) *UnionFind {
    parent := make([]int, n)
    size := make([]int, n)
    for i := range n {
        parent[i] = i
        size[i] = 1
    }
    return &UnionFind{
        parent: parent,
        size:   size,
        groups: n,
    }
}

func (this *UnionFind) Find(x int) int {
    if this.parent[x] != x {
        this.parent[x] = this.Find(this.parent[x])
    }
    return this.parent[x]
}

func (this *UnionFind) Union(x, y int) {
    rx, ry := this.Find(x), this.Find(y)
    if rx == ry {
        return
    }
    this.groups--
    if this.size[rx] > this.size[ry] {
        rx, ry = ry, rx
    }
    this.parent[rx] = ry
    this.size[ry] += this.size[rx]
}

func (this *UnionFind) IsUnion(x, y int) bool {
    return this.Find(x) == this.Find(y)
}

func (this *UnionFind) Groups() int {
    return this.groups
}