并查集

标签: 并查集

  • 并查集子节点纸箱父节点
  • 判断网络中连接的状态
    • 网络是个抽象概念:用户之间形成的网络(好友之间,音乐之间,图书之间,路由器之间,交通网络)
public interface UF {
    int getSize() ;
    //查看2个元素是否相连的
    boolean isConnected (int p,int q);
    //将2个元素放在一起
    void unionElements(int p,int q);
}
public class UnionFind1 implements  UF {
    private int[] id;
    public UnionFind1(int size){
        id =new int[size];
        for(int i =0;i<id.length;i++)
            id[i] = i;
    }
    @Override
    public int getSize() {
        return id.length;
    }

    @Override
    public boolean isConnected(int p, int q) {
        return (find(p) ==find(q));
    }

    @Override
    public void unionElements(int p, int q) {
        int pId =find(p);
        int qId = find(q);
        for (int i = 0;i<id.length;i++)
            if(id[i] == pId)
                id[i] = qId;
    }
    private int find(int p){
        if(p<0 && p>=id.length)
            throw  new IllegalArgumentException("index out of bound.");
        return id[p];
    }


}

unionElements O(N)
isConnected O(1)

在这里插入图片描述

在这里插入图片描述

并查集 通过一个数组去记录 这些节点之间的关系:
举个比较容易理解的例子 假设 向以前抗战时期 中共地下党 之间的间谍他们为了防止中间出现叛徒 即使属于同一个组织 但是也不一定认识 但是每个人 都会有一个联络人 有一个代号 通过暗号交流 要交接任务只能联系上级 只有职位比较高的 才能知道地下和他联系的一级联络人 但是 即便这样 他下级的再下一级很多情况下也是没法知道的 因为地下党也可以自己发展下线而领导可能只知道有这么个人 只能通过一级一级的向上汇报之间的工作。
类比 并查集 也是类似的 数组 有数组索引(代号) 然后数组存储的值 就是别的数组的 索引(代号) a[长江] = 黄河 区别只是 在数组里面索引为 0,1,2,3的顺序数字 做下改变 令 长江为 0 黄河为1 就变成 a[0] = 1 a[1]=xxx
这样就形成了 关系之间的关联 。

public class UnionFind2 implements UF{
    private int[] parent;
    public  UnionFind2(int size){
        parent = new int[size];
        for (int i=0;i<parent.length;i++){
            parent[i] = i;
        }

    }

    @Override
    public int getSize() {
        return parent.length;
    }
    private int find(int p){
        if(p<0 && p>=parent.length)
            throw  new IllegalArgumentException("index out of bound.");
        //根节点 就是 索引和值都等于自己的 所以 如果索引何止不匹配就去找他的上级 复杂度O(h) h层数
        while(p!=parent[p])
            p =parent[p];
        return p;
    }

    @Override
    public boolean isConnected(int p, int q) {
        return find(p)==find(q);
    }

    @Override
    public void unionElements(int p, int q) {
        //找到 p最上面的节点
        int pRoor =find(p);
     	//找到 q最上面的节点
        int qRoot =find(q);
        //如果都在一个领导手下 那就不要合并了
        if(pRoor ==qRoot)
            return;
         //否则p合并到q的领导的下级去
        parent[pRoor] = qRoot;
    }
}

基于size优化

在合并的时候 看 如果 p的根节点 的数节点 远大于 q 的 根节点 那 向q合并 并 跟新q根节点子节点数量

//用来记录节点下的子节点数量
private int[] sz;
 @Override
    public void unionElements(int p, int q) {
        int pRoor =find(p);
        int qRoot =find(q);
        if(pRoor ==qRoot)
            return;
        if(sz[pRoor] <sz[qRoot]){
            parent[pRoor] = qRoot;
            sz[qRoot] += sz[pRoor];
        }else{
            parent[qRoot] =pRoor;
            sz[pRoor] += sz[qRoot];
        }

    }

基于rank 优化

private int[] rank;
@Override
    public void unionElements(int p, int q) {
        int pRoor =find(p);
        int qRoot =find(q);
        if(rank[pRoor] <rank[qRoot]){
            parent[pRoor] =qRoot;
        }else if(rank[pRoor] >rank[qRoot])
            parent[qRoot] =pRoor;
        else{
            parent[qRoot] =pRoor;
            rank[pRoor] += 1;
        }


    }

基于路径压缩

parent[p] = parent[parent[p]];
版权声明:本文为weixin_41315492原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_41315492/article/details/102571800

智能推荐

*********(北大)并查集**********

目录 POJ 1703 Find them, Catch them // 种类并查集 自己的详细理解过程 回溯过程 POJ 1611 The Suspects POJ 1988 Cube Stacking POJ 1182 食物链   POJ 1703 Find them, Catch them // 种类并查集 自己的详细理解过程 回溯过程   ...

并查集

并查集是由一群集合构成,最开始时所有元素各自单独构成一个集合。 当集合中只有一个元素时,这个集合的代表节点即为该元素,该元素的father也是自己。 使用哈希表来存并查集中所有集合的所有元素的father信息,记为fatherMap。fatherMap中的一条记录所代表的含义是key节点的father为value节点。每个节点都有father信息。集合代表节点的father为本身。 另外还会存储r...

并查集

并查集(Union-Find) 参考博客 wiki 解决的问题 并查集解决的是一个 连接问题 并查集支持两个操作: union(p,q) 并! 两个节点所在的集合合并 find(p) 查! 查询根节点 回答一个问题: isConneted(p,q) : 两个节点是否连通. 只需给出是否连通. 不需要给出具体路径. 建模思路 对于所有连通的节点. 认为他们是一个组. 因此不连通的节点必然不在同一个组...

并查集

目录 1558.Segment set 1811.Rank of Tetris 1829.A Bug's Life 1198.Farm Irrigation 1558.Segment set A segment and all segments which are connected with it compose a segment set. The size of a segment set ...

查并集

并查集是我暑假从高手那里学到的一招,觉得真是太精妙的设计了。以前我无法解决的一类问题竟然可以用如此简单高效的方法搞定。不分享出来真是对不起party了。(party:我靠,关我嘛事啊?我跟你很熟么?) 来看一个实例,HDU1232畅通工程 首先在地图上给你若干个城镇,这些城镇都可以看作点,然后告诉你哪些对城镇之间是有道路直接相连的。最后要解决的是整幅图的连通性问题。比如随意给你两个点,让你判断它们...

猜你喜欢

并查集

太有意思了! 看完绝对会用并查集了; 转载:http://blog.csdn.net/dellaserss/article/details/7724401/ 请看! 讲了并查集和路径压缩算法! 并查集是我暑假从高手那里学到的一招,觉得真是太精妙的设计了。以前我无法解决的一类问题竟然可以用如此简单高效的方法搞定。不分享出来真是对不起party了。(party:我靠,关我嘛事啊?我跟你很熟么?) 来看...

并查集

并查集:查找 一个元素所属的集合,合并俩个元素所在各自的集合。 查找一个元素所属的集合,就要找到这个元素对应的节点所在的分离集合树; 分离集合树:每个分离集合对应的一棵树 下面是俩颗分离集合树,代表俩个集合   以第一颗树为例,1和3认识,3和4认识,4和2认识,每个元素都是自己的集合,将1合并到3所在的集合,将3合并到4所在的集合,2合并到4的集合,如果找到4的集合是它自己,则这几个元...

查并集

今天来补之前刷过的专题,查并集是一个比较简单的专题:查并集有三种类型,第一种类型是普通查并集,第二个就带权查并集 第三种就是种类查并集 第一种简单查并集主要就是那两个函数:  通过找根节点是否相同,然后再进行合并树。查询他们是否相关的时候就是查询他们的根节点是否相等。 带权并查集:就是通过计算不同顶点到达根节点的距离,然后将他们的差%rand来判断两个顶点之间的关系,sum[i]数组就是...

并查集

  并查集(两个优化—按秩合并、路径压缩) 题目背景板  n个集合 m个操作 操作: 1 a b 合并a,b所在集合 2 a b 询问a,b是否属于同一集合,是则输出1否则输出0    话说并查集      并查集,并查集,合并 和 查找 集合 请发挥你丰富的想象 1 有一些班级 ,里面...

人工智能基础-数学方法-形式逻辑

1956 年召开的达特茅斯会议宣告了人工智能的诞生。在人工智能的襁褓期,各位奠基者们,包括约翰·麦卡锡、赫伯特·西蒙、马文·明斯基等未来的图灵奖得主,他们的愿景是让“具备抽象思考能力的程序解释合成的物质如何能够拥有人类的心智”。 通俗地说,理想的人工智能应该具备抽象意义上的学习、推理与归纳能力,其通用性将远远强于解决国际象棋或是围棋...