美文网首页
Union-Find

Union-Find

作者: 大橙子CZ | 来源:发表于2016-05-25 23:29 被阅读0次

Quick Find

数组的每个位置存相应的节点id,相连接的节点的位置存相同的id。
判断是否相连(connected)只需判断两位置的id是否相同。
而将两节点连接起来(union)则需要将第一个节点的id下所有的节点都更改为第二个节点的id。

public class QuickFind{
    private int[] id;
    public QuickFind(int N){
        id = new int[N];
        for(int i = 0;i < N;i++){
            id[i] = i;  
        }
    }

    //判断是否相连
    public boolean connected(int p,int q){
        return id[p]==id[q];
    }

    //将两点相连
    public  void union(int p,int q){
        int pid = id[p];
        int qid = id[q];
        if(pid == qid){
            return;
        }
        for(int i  = 0;i<id.length;i++){
            if(id[i] == pid){
                id[i] = qid;
            }
        }
    }
}

在上述程序中,查找(connected)的时间复杂度为O(1),而union和initialize的时间复杂度均为O(N)。

Quick Union

数组的每个位置存的是其父节点;
判断两个节点是否相连(connected)需判断两节点是否有相同的根节点。
将两个节点连接(union)则只需将第一个节点的根节点作为第二个节点根节点的孩子即可。

public class QuickFind{
    private int[] id;
    public QuickFind(int N){
        id = new int[N];
        for(int i = 0;i < N;i++){
            id[i] = i;  
        }
    }

    //找根节点
    public int root(int q){
        while(id[q] != q){
            q = id[q];
        }
        return q; 
    }

    //判断是否相连
    public boolean connected(int p,int q){
        return root(p)==root(q);
    }

    //将两点相连
    public void union(int p,int q){
        id[root(p)] = root(q);
    }
}

由于查找和归并都需要找根节点,因此这里面所有的方法时间复杂度都为O(N)。

Quick-Union Improvements

由于quick union中可能会碰到tall tree,那么寻找其根节点就是一个很耗时的工作。
改进算法中应用了 weighted algorithm,也就是在连接的时候每次将较小的tree连到较大的tree上,避免让较大的tree在某个tree的底部从而使这个tree变得很长。
此时需要另一个数组sz存储每个tree的大小。

public class QuickFind{
    private int[] id;
    private int[] sz;
    public QuickFind(int N){
        id = new int[N];
        sz = new int[N];
        for(int i = 0;i < N;i++){
            id[i] = i;  
            sz[i] = 1;
        }
    }

    //找根节点
    public int root(int q){
        while(id[q] != q){
            q = id[q];
        }
        return q; 
    }

    //判断是否相连
    public boolean connected(int p,int q){
        return root(p)==root(q);
    }

    //将两点相连
    public void union(int p,int q){
        int i = root[p];
        int j = root[q];
        if(i==j){
            return;
        }
        if(sz[i]<sz[j]){
            id[i] =j;
            sz[j]+=sz[i];
        }else{
            idj] = i;
            sz[i]+=sz[j];
        } 
    }
}

拥有N个节点的树的最大深度为logN。因此此方法中connected和union的时间复杂度应为O(logN)

更进一步的改进:path compression

在搜索根节点时会走过路径上的所有点,莫不如将路径上的所有点都直接加到根节点上。为了时间复杂度的效率及代码的简洁性,考虑将路径上的每一个节点加到其祖父节点(grandparent)下。

public int root(int q){
        while(id[q] != q){
            id[q] = id[id[q]];//将该节点加到其祖父节点下
            q = id[q];
        }
        return q; 
    }

http://visualgo.net/ufds 展示的为最后path compression的做法(搜索根节点时将路径上每个结点加到根节点上)。

相关文章

  • Union-Find

    261. Graph Valid Tree Given n nodes labeled from 0 to n-1...

  • Union-Find

    Dynamic connectivity Quick-find Quick-union [lazy approac...

  • Union-Find

    目录页:我的algs4之旅 Union-Find是Algorithms, Part I第一周的第二部分。该部分的编...

  • union-find

    问题: 输入数据必须为(0,n)?输入数据是(0-n),初始化的时候会把id[]中的值赋值为(0-n)的数 uni...

  • Union-Find

    用于解决动态连通图的连接性问题 问题描述 给定由N个对象构成的集合,并告知哪些对象之间是连通的,由此判断某两个对象...

  • Union-Find

    Quick Find 数组的每个位置存相应的节点id,相连接的节点的位置存相同的id。判断是否相连(connect...

  • 8.16 - hard - 59

    305. Number of Islands II 一道union-find的题目,这类题目只要找准谁是boss就...

  • Union-Find算法

    动态连通性问题中,如何判断触点是否相连接,可以抽象表述为如何编写程序来过滤掉序列中所有无意义的整数对。连通性问题只...

  • union-find算法

    Api: 加权quick-union算法:将小数的根节点连接到大树的根节点 最优解法:路径压缩的加权quick-u...

  • union-find 算法

    1、前言 union-find 为并查集算法,原本的用途是判断图的连通性问题,连通性是指图中的两个节点是否相连。说...

网友评论

      本文标题:Union-Find

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