并查集(Union-Find)详解 + Java 完整实现

目录

一、核心概念

[1. 本质](#1. 本质)

[2. 两个核心操作](#2. 两个核心操作)

[3. 两大优化(必须掌握)](#3. 两大优化(必须掌握))

[二、Java 代码实现(完整版,带优化)](#二、Java 代码实现(完整版,带优化))

三、代码核心讲解

[1. 初始化](#1. 初始化)

[2. find () + 路径压缩(关键)](#2. find () + 路径压缩(关键))

[3. union () + 按秩合并(关键)](#3. union () + 按秩合并(关键))

[4. 常用工具方法](#4. 常用工具方法)

四、测试代码(验证功能)

五、并查集适用场景(高频面试题)

六、二维网格并查集(扩展,面试常考)

总结


并查集(Union-Find / Disjoint Set Union,DSU )是一种处理动态连通性问题的数据结构,核心解决两个问题:

  1. 查询:两个元素是否在同一个集合中
  2. 合并:将两个不同的集合合并为一个

它的效率极高,均摊时间复杂度接近 O (1),是图论、最小生成树(Kruskal)、朋友圈问题、岛屿问题的核心算法。


一、核心概念

1. 本质

用一个数组parent[] 表示元素的父节点:

  • parent[i] = j:元素 i 的父节点是 j
  • 根节点parent[i] = i(自己是自己的父节点,代表整个集合)

2. 两个核心操作

  1. find(x) :查找元素 x 所在集合的根节点(用于判断连通性)
  2. union(x, y) :合并 xy 所在的两个集合

3. 两大优化(必须掌握)

不优化的并查集会退化成链表,效率极低,必须加这两个优化

  1. 路径压缩:查询时直接让节点指向根节点,抹平树的高度
  2. 按秩合并 :合并时把小树挂到大树下,避免树越来越高

二、Java 代码实现(完整版,带优化)

这是工业级标准实现,支持初始化、查询、合并、统计连通分量,直接复制可用。

复制代码
public class UnionFind {
    // 父节点数组:parent[i] 表示 i 的父节点
    private int[] parent;
    // 秩数组:记录树的高度/大小,用于按秩合并
    private int[] rank;
    // 连通分量的个数(独立集合的数量)
    private int count;

    // 构造方法:初始化并查集,元素范围 0 ~ n-1
    public UnionFind(int n) {
        parent = new int[n];
        rank = new int[n];
        count = n; // 初始每个元素自己是一个集合

        for (int i = 0; i < n; i++) {
            parent[i] = i; // 初始父节点是自己
            rank[i] = 1;   // 初始树高度为1
        }
    }

    // 【核心1】查找根节点 + 路径压缩
    public int find(int x) {
        // 递归写法:简洁,推荐
        if (parent[x] != x) {
            // 路径压缩:直接让x指向根节点
            parent[x] = find(parent[x]);
        }
        return parent[x];

        // 迭代写法(避免栈溢出,大数据量推荐)
        /*
        while (parent[x] != x) {
            parent[x] = parent[parent[x]]; // 路径压缩
            x = parent[x];
        }
        return x;
        */
    }

    // 【核心2】合并两个集合 + 按秩合并
    public void union(int x, int y) {
        int rootX = find(x);
        int rootY = find(y);

        //  already in the same set
        if (rootX == rootY) {
            return;
        }

        // 按秩合并:小树挂到大树下
        if (rank[rootX] < rank[rootY]) {
            parent[rootX] = rootY;
        } else if (rank[rootX] > rank[rootY]) {
            parent[rootY] = rootX;
        } else {
            // 高度相同,合并后高度+1
            parent[rootY] = rootX;
            rank[rootX]++;
        }
        // 合并成功,连通分量-1
        count--;
    }

    // 判断两个元素是否连通
    public boolean isConnected(int x, int y) {
        return find(x) == find(y);
    }

    // 获取当前连通分量的数量
    public int getCount() {
        return count;
    }
}

三、代码核心讲解

1. 初始化

  • 每个元素的父节点是自己,自己是独立集合
  • count 初始等于元素总数

2. find () + 路径压缩(关键)

复制代码
parent[x] = find(parent[x]);

作用:让查询路径上的所有节点直接指向根节点,下次查询直接 O (1) 找到根。

3. union () + 按秩合并(关键)

  • 先找两个节点的根
  • 根不同才合并
  • 小树挂大树,保证树始终是 "矮胖" 的,效率最高

4. 常用工具方法

  • isConnected(x,y):判断连通
  • getCount():获取独立集合数量

四、测试代码(验证功能)

复制代码
public class Main {
    public static void main(String[] args) {
        // 初始化 5 个元素:0,1,2,3,4
        UnionFind uf = new UnionFind(5);

        // 合并 0-1,2-3,0-2
        uf.union(0, 1);
        uf.union(2, 3);
        uf.union(0, 2);

        // 查询
        System.out.println(uf.isConnected(0, 3)); // true
        System.out.println(uf.isConnected(0, 4)); // false
        System.out.println(uf.getCount());        // 2 个连通分量:{0,1,2,3}, {4}
    }
}

五、并查集适用场景(高频面试题)

只要题目出现连通、合并、分组、朋友圈、岛屿、家族等关键词,直接用并查集:

  1. 朋友圈问题:多少个朋友圈
  2. 岛屿数量:二维网格并查集
  3. 最小生成树 Kruskal 算法
  4. 判断图是否有环
  5. 等式方程的可满足性
  6. 冗余连接

六、二维网格并查集(扩展,面试常考)

如果是二维坐标 (x,y),只需要做一个坐标映射:

复制代码
// 二维坐标转一维:x 行 y 列,总列数 cols
int index = x * cols + y;

就能直接用上面的并查集类。


总结

  1. 并查集 = 查找 (find) + 合并 (union)
  2. 两大优化:路径压缩 + 按秩合并(必须写)
  3. 时间复杂度:几乎 O (1)
  4. 适用场景:动态连通性问题
相关推荐
WL_Aurora1 小时前
Java集合框架核心组件
java
我是一颗柠檬1 小时前
【JDK8新特性】Stream流API上Day4
java·开发语言·后端
超梦dasgg1 小时前
拆分大对象 + 流式处理 + 不一次性加载全量数据
java·jvm·windows
仍然.1 小时前
算法题目---队列+宽搜(BFS)
算法·宽度优先
我是一颗柠檬1 小时前
【JDK8新特性】方法引用与构造器引用Day3
java·开发语言·后端·intellij-idea
在繁华处1 小时前
从零搭建轻灵(五):记忆系统与生产化特性
java·jvm·oracle
AbandonForce1 小时前
从入门到入土:二分查找算法
数据结构·算法
L_09071 小时前
【C++】数据结构之哈希表(散列表)
数据结构·c++·散列表
天若有情6731 小时前
Deepseek-V4-Flash-20260423 深度评测与实战指南
java·大数据·网络·ai