算法篇 : 并查集

介绍

英文名:union find set

作用:合并集合,查询集合

合并:将有直接关系的顶点放在一个集合里面

查找:查询某个顶点所属的集合

集合的标志:用祖先点的标号作为每个集合的标识

案例

如果说将下图的集合2合并至集合1

那么应该让3的祖先为1,即:

实现流程

1)对所有顶点标号,其祖先节点默认为自己

2)合并:以两个点中祖先标号小的作为新祖先进行合并

3)查找:查找点的祖先,并更新查找路径点的祖先

Java代码实现
java 复制代码
//顶点类
public class Vertex {
    public Integer id;
    public Vertex(Integer id){
        this.id=id;
    }
}

//并查集的操作类
public class UnionFindSetOperator {
    private List<Vertex>vertexs;    //所有顶点
    private List<List<Vertex>>connectVertexs;    //所有有直接关系的顶点
    private Map<Vertex,Vertex>ancestor;
    public UnionFindSetOperator(List<Vertex> vertexs, List<List<Vertex>> connectVertexs) {
        this.vertexs = vertexs;
        this.connectVertexs = connectVertexs;
        this.ancestor=new HashMap<>();
        //将所有顶点的祖先初始化默认设置为自己
        for(int i=0;i< vertexs.size();i++)
        {
            ancestor.put(vertexs.get(i),vertexs.get(i));
        }
        //合并所有直接相连的顶点
        for(int i=0;i< connectVertexs.size();i++)
        {
            Union(connectVertexs.get(i).get(0),connectVertexs.get(i).get(1));
        }
    }
    public void Union(Vertex vertex1,Vertex vertex2){
        Vertex ancestor1=Find(vertex1);
        Vertex ancestor2=Find(vertex2);
        //选取两个祖先id小的作为新祖先
        if(ancestor1.id<ancestor2.id)
            ancestor.put(vertex2,ancestor1);
        else
            ancestor.put(vertex1,ancestor2);
    }

    public Vertex Find(Vertex vertex){
        if(ancestor.get(vertex)!=vertex)
        {
            //寻找该节点的祖先
            Vertex ancestorVertex=Find(ancestor.get(vertex));
            //如果祖先发生了变化,则更新记录新的祖先
            if(ancestorVertex!=ancestor.get(vertex))
                ancestor.put(vertex,ancestorVertex);
        }
        //返回其祖先
        return ancestor.get(vertex);
    }
}
测试函数
java 复制代码
//测试函数
public class Main {
    /*
        并查集:
            简述:对集合进行分类合并,方便后续查找
            实现步骤:
                1)对所有顶点标号,其祖先节点默认为自己

                2)合并:以两个点中祖先标号小的作为新祖先进行合并

                3)查找:查找点的祖先,并更新查找路径点的祖先

     */
    public static void main(String[] args) {
        //扫描器
        Scanner scanner=new Scanner(System.in);

        //存放顶点
        List<Vertex>vertexs=new LinkedList<>();

        //有直接关联的顶点
        List<List<Vertex>>connectVertexs=new LinkedList<>();

        System.out.println("请输入顶点的数量:");
        Integer vexcnt= scanner.nextInt();

        System.out.println("请输入这些顶点的编号");
        for(int i=0;i<vexcnt;i++)
        {
            vertexs.add(new Vertex(scanner.nextInt()));
        }

        System.out.println("请输入有关系顶点的对数:");
        Integer connectVertexCnt= scanner.nextInt();

        System.out.println("请输入有关系顶点的编号:");
        for(int i=0;i<connectVertexCnt;i++)
        {
            Integer id1= scanner.nextInt();
            Integer id2= scanner.nextInt();

            //获取这两个顶点
            Vertex v1=null;
            Vertex v2=null;

            for(int j=0;j<vertexs.size();j++)
            {
                if(vertexs.get(j).id==id1)
                    v1=vertexs.get(j);
                if(vertexs.get(j).id==id2)
                    v2=vertexs.get(j);
            }
            LinkedList<Vertex>conVertexs=new LinkedList<>();
            conVertexs.add(v1);
            conVertexs.add(v2);
            connectVertexs.add(conVertexs);
        }

        //用并查集的操作类实现这些点的分类和查找
        UnionFindSetOperator ufs=new UnionFindSetOperator(vertexs,connectVertexs);

        //查找每一个点的祖先
        for(int i=0;i<vertexs.size();i++)
        {
            Vertex ancestor=ufs.Find(vertexs.get(i));
            System.out.println("顶点:"+vertexs.get(i).id+"的祖先id为:"+ancestor.id);
        }

    }
}
自测

测试模型:

测试结果:

相关推荐
lulu_gh_yu14 分钟前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法
~yY…s<#>2 小时前
【刷题17】最小栈、栈的压入弹出、逆波兰表达式
c语言·数据结构·c++·算法·leetcode
XuanRanDev3 小时前
【每日一题】LeetCode - 三数之和
数据结构·算法·leetcode·1024程序员节
代码猪猪傻瓜coding3 小时前
力扣1 两数之和
数据结构·算法·leetcode
南宫生4 小时前
贪心算法习题其三【力扣】【算法学习day.20】
java·数据结构·学习·算法·leetcode·贪心算法
weixin_432702265 小时前
代码随想录算法训练营第五十五天|图论理论基础
数据结构·python·算法·深度优先·图论
passer__jw7676 小时前
【LeetCode】【算法】283. 移动零
数据结构·算法·leetcode
爱吃生蚝的于勒7 小时前
深入学习指针(5)!!!!!!!!!!!!!!!
c语言·开发语言·数据结构·学习·计算机网络·算法
羊小猪~~7 小时前
数据结构C语言描述2(图文结合)--有头单链表,无头单链表(两种方法),链表反转、有序链表构建、排序等操作,考研可看
c语言·数据结构·c++·考研·算法·链表·visual studio
脉牛杂德7 小时前
多项式加法——C语言
数据结构·c++·算法