基础算法学习:并查集

基础算法学习:并查集

并查集(Union-Find) 是一种用于处理集合合并和查询的高效数据结构。它支持两种操作:

  1. 合并(Union) :将两个集合合并成一个集合。
  2. 查找(Find) :查找某个元素所在的集合(即查找元素的代表)。

并查集通常用于解决一些动态连通性问题,例如图的连通性问题、网络连接问题等。

并查集的基本思想:

并查集维护了一个集合(或树)的集合。每个集合由一个元素的代表(通常是树的根节点)表示。每个元素指向其父元素(指向树中的父节点),根节点指向自己。通过路径压缩按秩合并技术,能够使并查集操作更加高效。

主要操作:

  1. Find:查找某个元素所在的集合(即查找该元素的代表元素)。这通常是通过递归或者迭代查找元素的父节点实现的。

    • 路径压缩(Path Compression) :在查找时,通过将访问路径上所有节点直接指向根节点,从而加速未来的查询。
  2. Union:将两个集合合并成一个集合。通常,我们会将一个集合的根节点指向另一个集合的根节点。

    • 按秩合并(Union by Rank/Size) :为了保持树的平衡,通常会将较小的树合并到较大的树上,避免树的深度过大,从而提高查找效率。

并查集的时间复杂度:

通过路径压缩和按秩合并,虽然并查集的操作理论上是树形结构,但树的高度保持非常低,实际时间复杂度接近于 O(α(n)) ,其中 α(n) 是 阿克曼函数的反函数,其增长极其缓慢,因此在实际中可以认为是常数时间。


并查集板子

(1)朴素并查集:

    int p[N]; //存储每个点的祖宗节点

    // 返回x的祖宗节点
    int find(int x)
    {
        if (p[x] != x) p[x] = find(p[x]);
        return p[x];
    }

    // 初始化,假定节点编号是1~n
    for (int i = 1; i <= n; i ++ ) p[i] = i;

    // 合并a和b所在的两个集合:
    p[find(a)] = find(b);


(2)维护size的并查集:

    int p[N], size[N];
    //p[]存储每个点的祖宗节点, size[]只有祖宗节点的有意义,表示祖宗节点所在集合中的点的数量

    // 返回x的祖宗节点
    int find(int x)
    {
        if (p[x] != x) p[x] = find(p[x]);
        return p[x];
    }

    // 初始化,假定节点编号是1~n
    for (int i = 1; i <= n; i ++ )
    {
        p[i] = i;
        size[i] = 1;
    }

    // 合并a和b所在的两个集合:
    size[find(b)] += size[find(a)];
    p[find(a)] = find(b);


(3)维护到祖宗节点距离的并查集:

    int p[N], d[N];
    //p[]存储每个点的祖宗节点, d[x]存储x到p[x]的距离

    // 返回x的祖宗节点
    int find(int x)
    {
        if (p[x] != x)
        {
            int u = find(p[x]);
            d[x] += d[p[x]];
            p[x] = u;
        }
        return p[x];
    }

    // 初始化,假定节点编号是1~n
    for (int i = 1; i <= n; i ++ )
    {
        p[i] = i;
        d[i] = 0;
    }

    // 合并a和b所在的两个集合:
    p[find(a)] = find(b);
    d[find(a)] = distance; // 根据具体问题,初始化find(a)的偏移量
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值