union-find算法

动态连通性
问题描述:输入一列整数对,其中每个整数表示一个某种类型的对象,一对整数p、q可理解为p和q是相连的,假设相连是一种等价关系,其具有:

  • 自反性:p和p是相连的
  • 对称性:如果p和q相连,那么q和p也是相连的
  • 传递性:如果p和q是相连的且q和r是相连的,那么p和r也是相连的
    等价关系能够将对象分为多个等价类,当且仅当两个对象相连时他们才属于同一个等价类。连通性问题要求能够判断给定的整数对p、q是否相连;

union-find算法API

public class UF
UF(int N) 以整数标识(0~N-1)初始化N个触点
void union(int p, int q) 在p和q之间添加一条连接
int find(int p) p所在分量的标识符
boolean connected(int p, int q) 如果p和q存在于同一个分量中则返回true
int count() 连通分量的数量
/**
 * <b>类 名 称</b> :  QuickFind<br/>
 * <b>类 描 述</b> :  quick find算法实现<br/>
 * <b>创 建 人</b> :  zhudengkui<br/>
 * <b>创建时间</b> :  2021/2/27 22:51<br/>
 * <b>修 改 人</b> :  zhudengkui<br/>
 * <b>修改时间</b> :  2021/2/27 22:51<br/>
 * <b>修改备注</b> :  <br/>
 * quick-find算法分析:<br/>
 * find()操作的速度很快,它只需访问id[]数组一次,但其无法处理大型问题,因为对于每一次输入union()都需要
 * 扫描整个id[]数组。
 * @author zdk
 */
@SuppressWarnings("unused")
public class QuickFind implements UnionFindInterface {
    
    /**
     * 分量id,以触点作为索引(索引对应值为当前联通图跟节点的索引)
     */
    private int[] id;
    /**
     * 分量数量(联通图的个数)
     */
    private int count;
    
    public QuickFind(int n) {
        count = n;
        id =new int[n];
        for (int i = 0; i < n; i++) {
            id[i] = i;
        }
    }

    /**
     * 获取联通图的个数
     * @return 个数
     */
    @Override
    public int count() {
        return count;
    }

    /**
     * 判断p与q是否联通,即是否在同一联通图上
     * @param p p节点
     * @param q q节点
     * @return 是否联通
     */
    @Override
    public boolean connected(int p, int q) {
        return find(p) == find(q);
    }

    /**
     * 获取p节点所在图的跟节点
     * @param p p节点
     * @return 根节点索引
     */
    @Override
    public int find(int p) {
        return id[p];
    }

    /**
     * 联通两个节点
     * @param p p节点
     * @param q q节点
     */
    @Override
    public void union(int p, int q) {
        int pID = find(p);
        int qID = find(q);
        if (pID == qID) {
            return;
        }
        for (int i = 0; i < id.length; i++) {
            if (id[i] == pID) {
                id[i] = qID;
            }
        }
        count--;
    }
}
/**
 * <b>类 名 称</b> :  QuickUnion<br/>
 * <b>类 描 述</b> :  quick-union算法<br/>
 * <b>创 建 人</b> :  zhudengkui<br/>
 * <b>创建时间</b> :  2021/2/27 23:04<br/>
 * <b>修 改 人</b> :  zhudengkui<br/>
 * <b>修改时间</b> :  2021/2/27 23:04<br/>
 * <b>修改备注</b> :  <br/>
 * quick-union算法重点提高了union()方法的速度,它与quick-find算法互补,仅仅是find与union方法实现上的区别
 * @author zdk
 */
@SuppressWarnings("unused")
public class QuickUnion implements UnionFindInterface {
    
    /**
     * 分量id,以触点作为索引(索引值存储的是其父节点的索引,根节点为自己)
     */
    private int[] id;
    /**
     * 分量数量
     */
    private int count;
    
    public QuickUnion(int n) {
        count = n;
        id = new int[n];
        for (int i = 0; i < n; i++) {
            id[i] = i;
        }
    }
    
    @Override
    public int count() {
        return count;
    }
    
    @Override
    public boolean connected(int p, int q) {
        return find(p) == find(q);
    }
    
    @Override
    public int find(int p) {
        while (p != id[p]) {
            p = id[p];
        }
        return p;
    }
    
    @Override
    public void union(int p, int q) {
        int pID = find(p);
        int qID = find(q);
        if (pID == qID) {
            return;
        }
        id[pID] = qID;
        count--;
    }
}
/**
 * <b>类 名 称</b> :  QuickUnion<br/>
 * <b>类 描 述</b> :  union-find算法<br/>
 * <b>创 建 人</b> :  zhudengkui<br/>
 * <b>创建时间</b> :  2021/2/27 23:04<br/>
 * <b>修 改 人</b> :  zhudengkui<br/>
 * <b>修改时间</b> :  2021/2/27 23:04<br/>
 * <b>修改备注</b> :  <br/>
 * union-find算法(即加权quick-union算法):union中随意将一棵树连到另一颗树,现在我们会记录每棵树的大小,并总是将较小的树连接到较大的树上<br/>
 * 需要添加一个数组和一些代码来记录树中的节点数
 * @author zdk
 */
@SuppressWarnings("unused")
public class UnionFind implements UnionFindInterface {
    
    /**
     * 分量id,以触点作为索引
     */
    private int[] id;

    /**
     * 记录每棵树(分量)的大小
     */
    private int[] sz;
    /**
     * 分量数量
     */
    private int count;
    
    public UnionFind(int n) {
        count = n;
        id = new int[n];
        sz = new int[n];
        for (int i = 0; i < n; i++) {
            id[i] = i;
            sz[i] = 1;
        }
    }
    
    @Override
    public int count() {
        return count;
    }
    
    @Override
    public boolean connected(int p, int q) {
        return find(p) == find(q);
    }
    
    @Override
    public int find(int p) {
        while (p != id[p]) {
            p = id[p];
        }
        return p;
    }
    
    @Override
    public void union(int p, int q) {
        int pID = find(p);
        int qID = find(q);
        if (pID == qID) {
            return;
        }
        if (sz[pID] < sz[qID]) {
            id[pID] = qID;
            sz[qID] += sz[pID];
        } else {
            id[qID] = pID;
            sz[pID] += sz[qID];
        }
        count--;
    }
}

quick-find
quick-union

posted @ 2021-02-27 23:18  Abserver  阅读(45)  评论(0)    收藏  举报