美文网首页
[并查集]并查集的升级路线(一)

[并查集]并查集的升级路线(一)

作者: 铜炉 | 来源:发表于2021-02-11 21:16 被阅读0次

并查集是为了解决连通性问题,首先现将并查集模型定义出来。

首先并查集中存储的是是分量,不通分量可能存在连通关系,定义一个属性用来描述一个并查集中属于不通标识的分量个数,把并查集看做一个森林,这个count就是森林中树的数量。

并查集抽象父类定义

首先明确并查集中需要做的事情,并查集本省核心的方法就是两个,合并和查找,但是在此之上,我们需要将分量存储,以及连通的判断,所以经过分析,我们需要进行如下步骤。

  • 定义并查集分量集合,用数组存储,下标代表分量,对应值代表分量所在树的标识
  • 定义并查集森林中树的个数,每进行一次合并操作,树的个数减一。
  • 定义并查集构造方法。
  • 定义并查集中不同分量的连通性判断方法
  • 定义并查集的合并操作
  • 定义并查集的查找操作
package com.zt;

abstract public class UnionFind {

    // 存储连分量
    protected int[] id;
    // 当前并查集不同的连通分量总数
    protected int count;

    /**
     * 连通量构造方法
     *
     * @param n
     */
    public UnionFind(int n) {
        // 初始化时,没个分量互不连通
        this.count = n;
        // 初始化一个容纳全量分量的数组
        this.id = new int[n];
        for (int i = 0; i < n; i++) {
            // 没个分量初始值指向自身
            id[i] = i;
        }

    }

    /**
     * 判断两个分量是否连通
     *
     * @param p
     * @param q
     * @return
     */
    boolean connect(int p, int q) {
        // 如果两个分量的标识相等,代表两个分量连通
        return find(p) == find(q);
    }

    /**
     * 链接两个分量
     *
     * @param p
     * @param q
     */
    abstract void union(int p, int q);

    /**
     * 查找分量的标识
     *
     * @param p
     * @return
     */
    abstract int find(int p);

}

quick-find

quick-find是并查集的最初阶解决方案,从名字中可以看出,该算法的目的是要快速找到分量的标识,将查找复杂度定义在O(1)时间复杂度内,每次查找分量标识的时间控制在一次之内。

但是与此同时,union的操作会变得相对复杂很多,为了维护一级层级关系,最差的情况下,每次合并操作都需要改变当前合并的树的标识,那么该树下所有的分量全部都要改变标识。

具体实现步骤

  • 定义一个QuickFindUnionFind子类继承UnionFind
  • 实现查找方法。
  • 实现合并方法。
package com.zt;

/**
 * @author tian
 * @date 2021年2月11日 下午3:30:17
 * quick-find
 * 1 保证O(1)时间内找到分量标识
 * 2 合并分量时,将分量q及q所在的连通分两组中的所有分量的标识指向与p一致
 *
 * 优点:查找时间O(1)
 * 缺点
 */
public class QuickFindUnionFind extends UnionFind {
    /**
     * 连通量构造方法
     *
     * @param n
     */
    public QuickFindUnionFind(int n) {
        super(n);
    }

    @Override
    void union(int p, int q) {

        // 找到p的标识
        int pId = find(p);
        // 找到q的标识
        int qId = find(q);

        // 如果两个标识相等,代表已经合并
        if (pId == qId)  return;

        // 如果不相等,将分量q及q所在的连通分两组中的所有分量的标识指向与p一致
        for (int i = 0; i < id.length; i++) {
            if(id[i] == qId) id[i] = pId;
        }
        // 每次合并操作,会降低一个不同分量组
        count--;
    }

    @Override
    int find(int p) {
        return id[p];
    }
}

相关文章

  • [并查集]并查集的升级路线(一)

    并查集是为了解决连通性问题,首先现将并查集模型定义出来。 首先并查集中存储的是是分量,不通分量可能存在连通关系,定...

  • [并查集]并查集的升级路线(三)

    quick-union样本分析 在上一次的测试验证中,可以得出quick-union相对于quick-find算法...

  • [并查集]并查集的升级路线(二)

    quick-union quick-find是为了快速找到树的标识,quick-union顾名思义就是为了快速合并...

  • [并查集]并查集的升级路线(四)

    路径压缩并查集 并查集在经过了quick-find、quick-union、加权quick-union的演化之后,...

  • markdown学习

    #并查集 ##并查集的定义 ##并查集的操作

  • 并查集入门使用

    本文参考自《算法笔记》并查集篇 并查集的定义 什么是并查集?并查集可以理解为是一种维护数据集合的结构。名字中并查集...

  • 算法模板(四)并查集

    并查集 路径压缩并查集

  • [并查集]并查集应用之省份数量

    前言 经过并查集的升级路线一二三四之后,我们现在得到了一个相对来说比较完美的并查集数据结构,从本篇开始应用这个并查...

  • 并查集练习

    并查集 参考《算法笔记》 三要素:并,查,集。 并差集与一个算法有关,kruskal算法,就可通过并查集实现。 1...

  • 并查集

    并查集 并查集是什么 并查集是一种用来管理元素分组情况的数据结构,并查集可以高效地进行如下操作: 查询元素a和元素...

网友评论

      本文标题:[并查集]并查集的升级路线(一)

      本文链接:https://www.haomeiwen.com/subject/hkrlxltx.html