并查集算法

并查集算法简介

并查集(Disjoint Set Union,DSU)是一种用于管理元素分组的数据结构,支持两种核心操作:

  • 查找(Find):确定某个元素属于哪个集合(通常返回集合的代表元素)。
  • 合并(Union):将两个集合合并为一个集合。

常用于解决动态连通性问题,如网络连接、图的连通分量计算等。


核心实现方法

路径压缩优化(Find)

在查找时,将节点的父节点直接指向根节点,缩短后续查找路径。

int find(int x, vector<int>& parent) {
    if (parent[x] != x) {
        parent[x] = find(parent[x], parent); // 路径压缩
    }
    return parent[x];
}
按秩合并(Union)

合并时,将较小的树(按秩或大小)合并到较大的树下,避免树过高。

void unionSets(int x, int y, vector<int>& parent, vector<int>& rank) {
    int rootX = find(x, parent);
    int rootY = find(y, parent);
    if (rootX != rootY) {
        if (rank[rootX] > rank[rootY]) {
            parent[rootY] = rootX;
        } else if (rank[rootX] < rank[rootY]) {
            parent[rootX] = rootY;
        } else {
            parent[rootY] = rootX;
            rank[rootX]++;
        }
    }
}

时间复杂度分析

未优化版本
  • Find:最坏情况下为 O(n)O(n)O(n)(退化为链表)。
  • Union:依赖 Find 操作,同样为 O(n)O(n)O(n)
带路径压缩和按秩合并

通过优化,均摊时间复杂度接近常数:

  • Find 和 Union:均摊时间复杂度为 O(α(n))O(\alpha(n))O(α(n)),其中 α(n)\alpha(n)α(n) 是反阿克曼函数,增长极其缓慢(对于实际应用可视为常数)。
反阿克曼函数 α(n)\alpha(n)α(n)

定义为阿克曼函数 A(m,n)A(m, n)A(m,n) 的逆,满足:
A(α(n),n)≤log⁡nA(\alpha(n), n) \leq \log nA(α(n),n)logn
对于任何实际输入(如 n≤221019729n \leq 2^{2^{10^{19729}}}n221019729),α(n)≤4\alpha(n) \leq 4α(n)4


应用场景

  1. 动态连通性问题:判断图中两个节点是否连通。
  2. 最小生成树(Kruskal算法):按边权排序后使用并查集管理连通性。
  3. 社交网络分组:快速合并用户关系集合。

完整代码示例

#include <vector>
using namespace std;

class DSU {
private:
    vector<int> parent, rank;
public:
    DSU(int n) : parent(n), rank(n, 0) {
        for (int i = 0; i < n; ++i) parent[i] = i;
    }

    int find(int x) {
        if (parent[x] != x) {
            parent[x] = find(parent[x]);
        }
        return parent[x];
    }

    void unionSets(int x, int y) {
        int rootX = find(x);
        int rootY = find(y);
        if (rootX != rootY) {
            if (rank[rootX] > rank[rootY]) {
                parent[rootY] = rootX;
            } else {
                parent[rootX] = rootY;
                if (rank[rootX] == rank[rootY]) rank[rootY]++;
            }
        }
    }
};
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值