并查集算法--union find

一、动态连通性

  • 如果每个对中的两个整数分别代表一个网络节点,那么该对用来表示这两个节点连通,当所有的对建立了动态连通图后,就能够尽可能的减少布线,因为某些节点已经可以通过其他布线连通,可以直接忽略;在程序中,可以声明多个引用来指向同一对象,这个时候就可以通过为程序中声明的引用和实际对象建立动态连通图来判断哪些引用实际上是指向同一对象。
  • 方法:如果两个触点在不同的分量中,union()会将两个分量归并,每一次操作都会使分量总数减一。find()会返回给定触点所在的连通分量的标识符。connected()能够判断两个触点是否存在于同一个分量之中。count()会返回所有连通分量的数量。
package 图;

public class UnionFind {
    private int[] id;//分量触点
    private int count;//分量数量
    
    public UnionFind(int n){
        //初始化分量id数组
        count=n;
        id=new int[n];
        for (int i = 0; i < id.length; i++) {
            id[i]=i;
        }
    }
    public int getCount(){
        return count;
    }
    public boolean connected(int p,int q){
        return find(p)==find(q);
    }

    private int find(int p) {
        return id[p];
    }
    
    public void union(int p,int q){
        //将pq放到同一个分量中
        int pid=find(p);
        int qid=find(q);
        //如果pq已经在同一个分量中则不采取任何行动
        if(pid==qid)return;
        //否则将分量名称p重命名为q的分量
        for (int i = 0; i <id.length ; i++) {
            if (id[i]==pid){
                id[i]=qid;
            }
        }
        count--;
    }
}

 quick-union

   private int find(int p) {
        if(id[p]!=p)
            p=id[p];
        return id[p];
    }

    public void union(int p,int q){
        //将pq放到同一个分量中
        int pid=find(p);
        int qid=find(q);
        //如果pq已经在同一个分量中则不采取任何行动
        if(pid==qid)return;
        //否则将分量名称p重命名为q的分量
//        for (int i = 0; i <id.length ; i++) {
////            if (id[i]==pid){
////                id[i]=qid;
////            }
//        }
        id[pid]=qid;
        count--;
    }
  • 路径压缩的加权quick-union 算法:总是将较小的树连接到较大的树上,总的树的高度也在相应增加。构造的森林中的任意节点的深度最多为lgN
package 图;

public class WeightQuickUnionUF {
    private int[] id;
    private int[] sz;
    private int count;
    public WeightQuickUnionUF(int n){
        count=n;
        id=new int[n];
        for (int i = 0; i < id.length; i++) {
            id[i]=i;
        }
        sz=new int[n];
        for (int i = 0; i < sz.length; i++) {
            sz[i]=1;
        }
    }
    public int getCount(){return count;}
    public boolean connexted(int p, int q){
        return find(p)==find(q);
    }

    private int find(int q) {
        while (q!=id[q])q=id[q];//路径压缩,直接追寻到根节点
        return q;
    }
    
    public void union(int p,int q){
        int i=find(p);
        int j=find(q);
        if(i==j)return;
        if(sz[i]<sz[j]){
            id[i]=j;
            sz[j]=sz[i]+sz[j];
        }
        else {
            id[j]=i;
            sz[i]=sz[i]+sz[j];
        }
        count--;
    }
}

算法

存在N个触点时成本的增长数量级(最坏情况下)
构造函数 union() find()
quick-find算法 N N 1
quick-union算法 N 树的高度 树的高度
加权quick-find算法 N lgN lgN
使用路径压缩的加权quick-union 算法 N 非常接近但仍未达到1 均摊成本
理想情况 N 1 1
posted @ 2022-01-10 21:57  forever_fate  阅读(40)  评论(0)    收藏  举报