Kruskal算法求最小生成树(加边法)

news2024/11/17 11:22:17

一、算法逻辑

想要轻松形象理解Kruskal算法的算法逻辑,视频肯定比图文好。

小编看过很多求相关的教学视频,这里选出一个我认为最好理解的这一款安利给大家。

因为他不仅讲解细致,而且还配合了动画演示,可以说把一个抽象的东西讲的非常的形象了。

B站链接:【最小生成树(Kruskal(克鲁斯卡尔)和Prim(普里姆))算法动画演示】

二、JAVA实现

1、实现这个算法,要建立一个图,才可以,这里小编直接给一个,

基于邻接矩阵的图:

public class GraphByMatrix {

    private char[] arrayV;//顶点数组

    private int[][] matrix;//矩阵,存放每一个边的权重

    private boolean isDirect;//是否是有向图

    /**
     * 构造方法
     *
     * @param size     代表当前顶点的个数
     * @param isDirect  是否是有向图,true是有向图
     */

    public GraphByMatrix(int size, boolean isDirect) {
        this.arrayV = new char[size];//顶点的个数是size
        matrix = new int[size][size];
        for (int i = 0; i < size; i++) {
            Arrays.fill(matrix[i], Constant.MAX);
        }
        this.isDirect = isDirect;
    }



    /**
     * @param srcV   起点
     * @param destV  终点
     * @param weight 权值
     */
    public void addEdge(char srcV, char destV, int weight) {//重载之一,用来建立普通图
        int srcIndex = getIndexOfV(srcV);
        int destIndex = getIndexOfV(destV);
        matrix[srcIndex][destIndex] = weight;
        //如果是无向图 那么相反的位置 也同样需要置为空
        if (!isDirect) {
            matrix[destIndex][srcIndex] = weight;
        }
    }

    /**
     * @param srcIndex 起点
     * @param desIndex 终点
     * @param weight   权重
     */
    public void addEdge(int srcIndex, int desIndex, int weight) {//重载两个之一,用来建立最小生成树

        matrix[srcIndex][desIndex] = weight;
        //如果是无向图 那么相反的位置 也同样需要置为空
        if (!isDirect) {
            matrix[desIndex][srcIndex] = weight;
        }
    }


    /**
     * 获取顶点V的下标
     *
     * @param v
     * @return
     */
    private int getIndexOfV(char v) {
        for (int i = 0; i < arrayV.length; i++) {
            if (arrayV[i] == v) {
                return i;
            }
        }
        return -1;
    }

  
    public void printGraph() {
        for (int i = 0; i < arrayV.length; i++) {
            System.out.print(arrayV[i] + " ");
        }
        System.out.println();
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[i].length; j++) {
                if (matrix[i][j] == Constant.MAX) {
                    System.out.print("∞ ");
                } else {
                    System.out.print(matrix[i][j] + " ");
                }
            }
            System.out.println();
        }
    }




    /**
     * 定义了一个边的抽象类
     * 用来存储边的
     */
    static class Edge {
        public int srcIndex;
        public int destIndex;
        public int weight;//权重

        public Edge(int srcIndex, int destIndex, int weight) {
            this.srcIndex = srcIndex;
            this.destIndex = destIndex;
            this.weight = weight;
        }
    }
    
    public static void main(String[] args) {


    }
}

接下来对克鲁苏卡尔算法进行实现:

因为树一定是无向图,而无向图,用邻接矩阵表示,有一个特点,等一下会用到,以下边这个无向图为例:

圆圈代表不存在边,1代表有边

我们发现这个矩阵代码

    /**
     * 克鲁苏卡尔算法
     * 求最小生成树(无向图)
     * 返回总权重
     * minTree同时也被建立
     *
     * @param minTree
     */
    public int kruskal(GraphByMatrix minTree) {

        /**
         * 第一步:对所有的边进行排序(从小到大)
         */
        PriorityQueue<Edge> minHeap = new PriorityQueue<>();//建立一个小根堆来实现排序
        int n=arrayV.length;
        for (int i = 0; i < n; i++) {


            for (int j = 0; j < n; j++) {

                /*
                 * i<j的原因:
                 * //因为是无向图,所以根据对称性,只用录入一个方向的边的权值即可
                 * */
                if (j < i && matrix[i][j] != Constant.MAX) {//邻接矩阵的元素如果是Constant.Max说明边不存在
                    minHeap.offer(new Edge(i, j, matrix[i][j]));//i到j,权值是matrix[i][j]
                }
            }
        }

        //程序到达此处,已经排序好所有的边了

        //初始化查集后,每一个元素都是独立的集合
        UnionFindSet unionFindSet=new UnionFindSet(n);//定义一个并查集,大小就是图顶点数

        int size=0;//记录已经寻找到的边的个数,只要等于n-1,最小生成树就找到了
int totalWeight=0;//用来记录最小总权值
        while(size<n-1&&!minHeap.isEmpty()){//如果不加!minHeap.isEmpty()这个条件,此图若没有最小生成树(所给的图不是连通图),那么程序会死循环
            Edge edge=minHeap.poll();//出一个边
            int src=edge.srcIndex;//起点下标
            int des=edge.destIndex;//终点下标
            if(!unionFindSet.isSameUnionFindSet(src,des)){//不是同一个集合,进来(如果是同一个集合,就代表形成了环!)
                minTree.addEdge(edge.srcIndex,edge.srcIndex,edge.weight);//给最小生成树增加一条边
                size++;//尺寸加加
                unionFindSet.union(src,des);//合并两个顶点构成的边
                totalWeight+=edge.weight;
            }
        }

        if(size==n-1){
            return totalWeight;
        }else{//size!=n-1说明所给的图,不是连通图,找不到最小生成树
            return -1;//返回一个无效值
        }

    }

是关于对角线对称的,这个要记住等一下会用到。

代码加注释:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1704822.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【软件设计师】网络安全

1.网络安全基础信息 网络安全的五个基本要素&#xff1a; 机密性&#xff1a;确保信息不暴露给未授权的实体或进程 完整性&#xff1a;只有得到允许的人才能修改数据&#xff0c;并且能判断出数据是否已被修改 可用性&#xff1a;得到授权的实体在需要时可以访问数据&#xff0…

Web安全:文件上传漏洞详解,文件上传漏洞原理、绕过方式和防御方案。

「作者简介」&#xff1a;2022年北京冬奥会网络安全中国代表队&#xff0c;CSDN Top100&#xff0c;就职奇安信多年&#xff0c;以实战工作为基础对安全知识体系进行总结与归纳&#xff0c;著作适用于快速入门的 《网络安全自学教程》&#xff0c;内容涵盖系统安全、信息收集等…

【Mac】 CleanMyMac X for mac V4.15.2中文修复版安装教程

软件介绍 CleanMyMac X是一款为Mac设计的优秀软件&#xff0c;旨在帮助用户优化其设备的性能并提供清理和维护功能。以下是 CleanMyMac X的一些主要功能和特点&#xff1a; 1.系统性能优化&#xff1a;软件可以扫描和修复潜在的性能问题&#xff0c;包括无效的登录项、大文件…

【设计模式】创建型-抽象工厂模式

前言 在软件开发领域&#xff0c;设计模式是一种被广泛接受的解决方案&#xff0c;用于解决特定问题并提供可维护和可扩展的代码结构。抽象工厂模式&#xff08;Abstract Factory Pattern&#xff09;是其中之一&#xff0c;它提供了一种方法来创建一系列相关或相互依赖的对象…

(三)MobaXterm、VSCode、Pycharm ssh连接服务器并使用

背景&#xff1a;根据前两篇文章操作完成后&#xff0c; 手把手教学&#xff0c;一站式安装ubuntu及配置服务器-CSDN博客 手把手教学&#xff0c;一站式教你实现服务器&#xff08;Ubuntu&#xff09;Anaconda多用户共享-CSDN博客 课题组成员每人都有自己的帐号了&#xff0…

上海亚商投顾:沪指震荡反弹 半导体产业链午后爆发

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 沪指昨日震荡反弹&#xff0c;尾盘涨幅扩大至1%&#xff0c;深成指、创业板指同步上行&#xff0c;科创50指数…

实时直播技术革新:视频汇聚管理EasyCVR平台助力景区游览体验全面升级

自年初以来&#xff0c;各地文旅热点不断。“温暖驿站”“背诗免票”“王婆说媒”等等&#xff0c;吸引了不少人奔赴远方。2024年在国人消费意愿榜上&#xff0c;旅游又一次占据榜首的位置&#xff0c;有三分之一以上的人&#xff0c;今年会在旅游方面增加消费。中国旅游的发展…

【已解决】./start-base.sh: line 5: $‘\r‘: command not found

问题&#xff1a;在linux下运行启动服务的脚本&#xff0c;提示很多‘\r’不可用。 原因&#xff1a;windows下编辑的文件&#xff0c;放在linux下运行&#xff0c;文件格式有问题&#xff0c;需要转换。 解决方法&#xff1a; 1、用vim编辑器打开文件 vim 文件名 2、进入…

Matplotlib(可视化)小案例

一.认识&#xff1a; Matplotlib是一个Python 2D绘图库&#xff0c;它可以在各种平台上以各种硬拷贝格式和交互式环境生成出具有出版品质的图形。Matplotlib可用于Python脚本&#xff0c;Python和IPython shell&#xff0c;Jupyter笔记本&#xff0c;Web应用程序服务器和四个图…

K8S-pod资源 探针

一.pod资源限制&#xff1a; 对pod资源限制原因&#xff1a;高并发占用所有的cpu资源、内存资源、会造成雪崩 当定义 Pod 时可以选择性地为每个容器设定所需要的资源数量。 最常见的可设定资源是 CPU 和内存大小&#xff0c;以及其他类型的资源。 方式&#xff1a; 对pod做…

二叉树的实现(递归实现)

前言&#xff1a;本文讲解通过递归的方式实现二叉树的一些基本接口。 目录 通过左右子树的方式实现二叉树&#xff1a; 二叉树的遍历&#xff1a; 求二叉树结点的个数&#xff1a; 二叉树所有节点的个数&#xff1a; 二叉树叶子节点的个数&#xff1a; 求第k层节点的节点…

学习编程对英语要求高吗?

学习编程并不一定需要高深的英语水平。我这里有一套编程入门教程&#xff0c;不仅包含了详细的视频讲解&#xff0c;项目实战。如果你渴望学习编程&#xff0c;不妨点个关注&#xff0c;给个评论222&#xff0c;私信22&#xff0c;我在后台发给你。 虽然一些编程资源和文档可能…

公务员申论答题稿纸

申论答题稿纸网上不太好找&#xff0c;这里给大家分享两个版本&#xff0c;一个是在PDD上买到的稿纸样式&#xff0c;一种是那种考场答题样式&#xff0c;每个题都给你留有答题位置。第一种合适大家日常练习&#xff0c;比如说练字&#xff0c;第二种就适合答题的时候用了。 …

硬盘的分区

目录 概念 硬盘的分区 实操 创建分区 fdisk&#xff08;<2T&#xff09; 创建文件系统 挂载 自动挂载&#xff08;永久挂载&#xff09; gpt区分 swap 交换分区 如何删除已挂载的分区 概念 硬盘&#xff1a;计算机的存储设备。&#xff08;如无特殊说明&#xff0…

区间预测 | Matlab实现GRU-Attention-KDE核密度估计多置信区间多变量回归区间预测

区间预测 | Matlab实现GRU-Attention-KDE核密度估计多置信区间多变量回归区间预测 目录 区间预测 | Matlab实现GRU-Attention-KDE核密度估计多置信区间多变量回归区间预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现GRU-Attention-KDE门控循环单元注意力…

移动端应用订阅SDK接入攻略

本文档介绍了联想应用联运移动端订阅SDK接入操作指南&#xff0c;您可在了解文档内容后&#xff0c;自行接入应用联运移动端订阅SDK。 接入前准备 1请先与联想商务达成合作意向。 2.联系联想运营&#xff0c;提供应用和公司信息&#xff0c;并获取商户id、app id、key&#…

Python编程之旅:从错误到精通的奇妙探险

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、初识Python编程的陷阱与解决方案 1. 语法错误&#xff1a;防范于未然 2. 逻辑错误&…

流媒体内网穿透/组网/视频协议转换EasyNTS上云网关如何更改密码?

EasyNTS上云网关的主要作用是解决异地视频共享/组网/上云的需求&#xff0c;网页对域名进行添加映射时&#xff0c;添加成功后会生成一个外网访问地址&#xff0c;在浏览器中输入外网访问地址&#xff0c;即可查看内网应用。无需开放端口&#xff0c;EasyNTS上云网关平台会向Ea…

shell脚本读写二进制文件

文章目录 shell脚本读写二进制文件读取二进制文件使用xxd命令使用od命令 写入二进制文件使用echo和printf 读取和修改二进制文件使用dd命令 组合使用工具 shell脚本读写二进制文件 在Shell脚本中处理二进制文件时&#xff0c;可以使用一些常用的命令和工具来读取和写入二进制数…

Leetcode刷题笔记5

76. 最小覆盖子串 76. 最小覆盖子串 - 力扣&#xff08;LeetCode&#xff09; 解法一&#xff1a; 暴力枚举 哈希表 先定义left和right&#xff0c;可以在随机位置 枚举一个位置向后找&#xff0c;找到一个位置之后&#xff0c;发现这段区间是一个最小的区间之后&#xff0c…