Kruskal算法代码实现

2023-11-18

package com.kruskal;

import java.util.Arrays;

public class KruskalCase {

    private int edgeNum;//边的个数
    private char[] vertexs;//顶点个数
    private int[][] matrix;//邻接矩阵
    private static final int INF = Integer.MAX_VALUE;//表示连个顶点不能连通

    public KruskalCase(char[] vertexs, int[][] matrix) {
        //拿到顶点数
        int vlen = vertexs.length;
        //初始化顶点,复制拷贝的方式
        this.vertexs = new char[vlen];
        for (int i = 0; i < vlen; ++i) {
            this.vertexs[i] = vertexs[i];
        }

        //初始化边,复制拷贝的方式,这种方式里面的改变不影响传入的改变
        this.matrix = new int[vlen][vlen];
        for (int i = 0; i < vlen; ++i) {
            for (int j = 0; j < vlen; ++j) {
                this.matrix[i][j] = matrix[i][j];
            }
        }

        //统计边的个数
        for (int i = 0; i < vlen; ++i) {
            for (int j = i+1; j < vlen; ++j) {
                if (matrix[i][j] != INF) {
                    edgeNum++;
                }
            }
        }


    }

    //打印邻接矩阵
    public void print() {
        System.out.println("邻接矩阵为:");
        for (int i = 0; i < vertexs.length; ++i) {
            for (int j = 0; j < vertexs.length; ++j) {
                System.out.printf("%12d", matrix[i][j]);
            }
            System.out.println();
        }
    }


    public static void main(String[] args) {
        char[] vertexs = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
        int[][] matrix = {
                {0, 12, INF, INF, INF, 16, 24},
                {12, 0, 10, INF, INF, 7, INF},
                {INF, 10, 0, 3, 5, 6, INF},
                {INF, INF, 3, 0, 4, INF, INF},
                {INF, INF, 5, 4, 0, 2, 8},
                {16, 7, 6, INF, 2, 0, 9},
                {14, INF, INF, INF, 8, 9, 0}};
        KruskalCase kruskalCase = new KruskalCase(vertexs, matrix);
        kruskalCase.print();
        System.out.println("没有排序");
        System.out.println(Arrays.toString(kruskalCase.getEdges()));

        EData[] edges=kruskalCase.getEdges();
        kruskalCase.sortEdges(edges);
        System.out.println(Arrays.toString(edges));
        kruskalCase.kruskal();
    }

    //对边进行排序,这里用冒泡排序
    private void sortEdges(EData[] edges) {
        for (int i = 0; i < edges.length - 1; ++i) {
            for (int j = 0; j < edges.length - i - 1; ++j) {
                if (edges[j].weight > edges[j + 1].weight) {
                    EData temp = edges[j];
                    edges[j] = edges[j + 1];
                    edges[j + 1] = temp;
                }
            }
        }
    }

    //返回顶点对应的下标,如果找不到返回-1
    private int getPosition(char ch) {
        for (int i = 0; i < vertexs.length; ++i) {
            if (ch == vertexs[i]) {
                return i;
            }
        }
        return -1;
    }

    //获取图中的边,放到EData[]数组,后面需要遍历数组
    //通过邻接矩阵matrix获取
    private EData[] getEdges() {
        int index = 0;
        EData[] edges = new EData[edgeNum];
        for (int i = 0; i < vertexs.length; ++i) {
            for (int j = i + 1; j < vertexs.length; ++j) {

                if (matrix[i][j] != INF) {
                    edges[index++] = new EData(vertexs[i], vertexs[j], matrix[i][j]);
                }
            }

        }
        return edges;
    }

    // 获取下标为i的顶点的终点,用于判断两个顶点的终点是否相同
    // ends:该数组记录了各个顶点对应的终点是哪一个, ends数组是在遍历过程中逐步形成的
    // i:   表示传入的顶点对应的下标
    // 返回的就是下标为i的顶点对应的终点的下标
    // 我感觉这个函数的设计太刁了,你如果觉得一般,那你就是大佬
    private int getEnd(int[] ends, int i){
        //这个循环的设计太牛了,大佬写的太吊了
        while (ends[i] !=0){
            i=ends[i];
        }
        return i;
    }

    public void kruskal(){
        int index=0; //表示最后结果数组中有多少条边, 理论行是n-1条
        int[] ends= new int[edgeNum];// 用于保存"已有最小生成树"中每一个顶点在最下生成树中的终点

        //创建结果数组,保存最小生成树
        EData[] rets= new EData[edgeNum];

        //获取图中所有边的集合 该示例一共12条边
        EData[] edges= getEdges();
        System.out.println(edges.length);

        //按照边的权值排序
        sortEdges(edges);

        //遍历边的数组edges,将便添加到最小生成树,判断是否构成回路,如果没有构成,就加入到结果数组rets
        for(int i=0;i<edges.length;++i){
            //获取第i条边的第一个顶点(起点)
            int p1=getPosition(edges[i].start);
            //获取第i条边的第二个顶点
            int p2=getPosition(edges[i].end);

            //获取p1这个顶点在已有最小生成树中的终点
            //第一次加入时,由于ends里面的值开始全为0.第一次相当于返回顶点下标,具体可以看getEnd()方法的具体实现
            //也就是说如果第一次加入时,m是等于怕p1的
            int m=getEnd(ends, p1);
            //获取p1这个顶点在已有最小生成树中的终点
            int n=getEnd(ends, p2);

            //是否构成回路
            if(m!=n){//不构成回路
                ends[m]=n;
                rets[index++]=edges[i];
            }

        }

        //统计并打印最小生成树,输出rets
        System.out.println("最小生成树");
        for(int i=0;i<index;++i){
            System.out.println(rets[i]);
        }



    }





}

class EData {
    char start;
    char end;
    int weight;

    public EData(char start, char end, int weight) {
        this.start = start;
        this.end = end;
        this.weight = weight;
    }

    @Override
    public String toString() {
        return "EData[<" + start +","+end+">="+ weight+"]" ;
        //return "EData{" + "start=" + start + ", end=" + end + ", weight=" + weight + '}';
    }
}

有什么疑问,可以评论或私信我

更多数据结构问题代码实现请查看一下链接

JavaTest/denglianbin/src/com · 邓联斌/deng_study - 码云 - 开源中国 (gitee.com)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Kruskal算法代码实现 的相关文章

  • 如何使用 UnboundID LDAP SDK 获取 LDAP 中的 DN 和用户 ID

    当我唯一的参数是用户 ID 时 我试图获取用户的 DN 可能不止一个 我还使用 UnboundID LDap SDK 如您所见 public String getCustomerAdminDN String uid String resul
  • 将 Uri 转换为字符串以及将字符串转换为 Uri

    我正在开发一些应用程序 它允许从 SD 卡中选择图像 将其保存到数据库中并为 ImageView 设置该值 我需要知道将 uri 转换为字符串以及将字符串转换为 uri 的方法 现在我使用了 Uri 的 getEncodedPath 方法
  • 如何从二维数组中仅打印单个列?

    我正在编写这个程序 我必须只打印二维数组的一列 而不是两者 for int i 0 i lt sjf length i for int j 0 j lt sjf i length j System out printf 5d 4s sjf
  • 如何为带有未确定的“?”的Java通用Map添加值值类型?

    我在 JDK 8 示例中看到过这种声明 Map
  • Android - 检测电容式触摸屏上的触摸压力?

    我听说过 MotionEvent e float press e getPressure 但这只会在没有触摸时返回 0 当我的手指触摸屏幕时返回 1 是否可以找到手指在触摸电容屏上施加的压力值 或者我的预感是否正确 即这只适用于电阻屏幕 M
  • 可以使用注解进行代码注入吗?

    我意识到这可能是一个已经被提出和回答的问题 但请耐心等待 我想知道是否可以使用注释将代码注入到类编译时 典型的示例是为对象的成员生成 getter 和 setter 这并不完全是我所需要的 但它可以说明基本思想 现在在互联网上我得到的基本答
  • 正则表达式查找两个字符之间的内部匹配

    环境 Java 我想匹配两个字符串之间的字符 这是一个例子 foo
  • 在 Spring Security 中创建自定义 PostAuthorize 方法

    我正在尝试创建一个自定义方法 用于预 后授权调用 如下所示 public class CustomLSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandl
  • 转换为 JSON 后保留 XMLGregorianCalendar 日期格式 - Jackson Lib

    我有一个对象 它有 2 个 XMLGregorianCalendar 对象 一个用于日期 另一个用于时间 我使用 Jackson 对象映射器将日期转换为 JSON 格式 转换前的日期为2014年2月10日 时间为11 15 00 转换为 J
  • Bean 属性不可读或具有无效的 getter 方法

    因此 我的任务是为注册表路由编写一个简单的 Web 应用程序 使用 Spring MVC 所以我有 路线 类 我想在其中保留起点 终点和中间点列表 但我不明白如何将值从 jsp 放入列表 例如使用 jstl 所以我决定解析一个字符串 pub
  • Java SSO 与 Wildfly 8、Java 1.8.0_45 和 Active Directory

    我对这个主题进行了很多搜索 但找不到解决方案 要求的简短描述 Wildfly 8 2 下 Web 应用程序上的 SSO 在 Active Directory 中验证 Windows 用户的身份 当 SSO 失败时回退到登录表单 在 Wild
  • 从两个数组中查找公共文件

    我正在尝试从两个数组中查找通用名称文件 我已将两个不同文件夹的文件名保存在两个不同的数组中 现在我正在创建一个通用文件数组 其中包含具有通用名称的文件 filenames 1 包含文件夹 1 中文件名称的数组 filename2 包含文件夹
  • Java 8 中函数类型全等 lambda 表达式的用法

    我对 的定义和用法感到困惑 Stream collect Supplier
  • 在 Tomcat 中触发内部 ServletRequest

    我正在使用 Quartz 来安排 Web 应用程序的后台任务 其中一些任务只是针对同一 Web 应用程序发出请求 我想避免依赖于任何类型的网络设置 例如 如果从数据中心内发出带有我自己域名的请求 则可能无法正确路由 是否有一个 Java A
  • 从 Apache Kafka 中的主题删除消息

    所以我是 Apache Kafka 的新手 我正在尝试创建一个简单的应用程序 以便我可以更好地理解 API 我知道这个问题在这里被问了很多 但是如何清除存储在主题上的消息 记录 我看到的大多数答案都说要更改消息保留时间或删除并重新创建主题
  • Android 自定义相机 - 在矩形内裁剪图像

    我有一个自定义相机应用程序 它有一个居中的矩形视图 如下所示 当我拍照时 我想忽略矩形之外的所有内容 该视图与我的 XML 视图中的 Camera Preview 或 SurfaceView 没有任何联系 如下所示
  • 使用 Swift 在 iOS 和 Android 之间共享核心代码

    我想要的是 使用 Swift 在 Android 和 iOS 之间共享非 UI 代码 问题 Android 具有 NDK 支持 允许您使用 Java 本机接口 JNI 运行 C 和 C 代码 不是 Objective C 我是一名Java程
  • java中的Anagram算法

    我想做字谜算法但是 这段代码不起作用 我的错在哪里 例如 des 和 sed 是字谜 但输出不是字谜 同时我必须使用字符串方法 不是数组 public static boolean isAnagram String s1 String s2
  • Jersey:返回字符串列表

    我尝试以 JSON 和 XML 形式返回 Jersey 中的字符串列表 我以为这会是微不足道的 我的第一次尝试是写这样的东西 GET Produces MediaType APPLICATION JSON MediaType APPLICA
  • 在 Groovy 中将整数转换为 BigDecimal

    假设我们有一个 groovy 函数作为参数BigDecimal void func BigDecimal bd 并在 groovy 的其他课程中再次调用它var func 0 这工作正常 但在 java 中它根本无法编译 我知道有一个构造函

随机推荐

  • 【MyBatis-Plus】详解Wrappers.<T> lambdaQuery()以及常用过滤方法

    Wrappers
  • Java 动态代理作用是什么?

    主要用来做方法的增强 让你可以在不修改源码的情况下 增强一些方法 在方法执行前后做任何你想做的事情 甚至根本不去执行这个方法 因为在 InvocationHandler的invoke方法中 你可以直接获取正在调用方法对应的 Method对象
  • linux kernel --component组件用法

    kernel component组件用法 linux component组件架构分析
  • 如何用mac搭建本地svn服务器(如何将mac变成版本管理服务器)

    前言 一 搭建本地svn服务器 1 建立代码库 2 配置文件修改 3 启动本地svn服务 二 搭建过程中常见问题 如果Mac os升级到10 0以上 自带的svn不支持了怎么办 三 mac本地使用svn软件管理svn库 cornerston
  • Linux多进程数据交换--共享内存

    个人博客地址 https cxx001 gitee io 基础 在linux系统开发当中 时常需要在多个进程之间交换数据 在多个进程之间交换数据 有很多方法 但最高效的方法莫过于共享内存 linux共享内存是通过tmpfs这个文件系统来实现
  • 第二十八节、基于深度学习的目标检测算法的综述(附代码,并附有一些算法英文翻译文章链接))...

    在前面几节中 我们已经介绍了什么是目标检测 以及如何进行目标检测 还提及了滑动窗口 bounding box 以及IOU 非极大值抑制等概念 这里将会综述一下当前目标检测的研究成果 并对几个经典的目标检测算法进行概述 本文内容来自基于深度学
  • APK 逆向工程 - 解析 apk 基本信息和方法调用图

    导读 在 Android 开发中 我们很少使用 Android 逆向去分析 apk 文件的 但是作为一个测试人员 我们要对这个 apk 文件进行一系列的分析 审核 测试 这篇文章讲解如何解析一个 apk 文件 主要从下面几方面介绍 解析前准
  • mysql show para_mysql中show命令的详细用法

    经过我测试的语句 show procedure status 显示数据库中所有存储的存储过程基本信息 包括所属数据库 存储过 程名称 创建时间等 show create procedure sp name 显示某一个存储过程的详细信息 a
  • MongoDB安装和批量写入

    本文主要以Ubuntu系统为例 记录安装部署MongoDB社区版 并进行批量数据写入 安装部署主要依据MongoDB官网指引 数据写入脚本为个人编写 如有需要可以直接使用 1 导入包管理系统使用的公钥 wget qO https www m
  • UML中依赖和关联,关联,聚合和组合的区别

    在UML中 依赖和关联经常无法进行区分 在类图中 不知道什么时候使用依赖 什么时候使用关联 来定义两个类之间的关系 今天看了一篇帖子 对这两种关系做了比较生动的区分 依赖指的是两个类之间发生的关系输入偶然发生的 例如人和船之间的关系就是这种
  • Video_Codec_SDK压缩编码视频并封装为MP4格式

    在深度学习处理视频过程中 通常是先解码视频获取视频帧并转为cv Mat后进行处理 本章介绍如何将处理后的图片使用GPU编码为视频码流并封装为MP4格式 开发硬件 I7 9750H GTX1660ti 操作系统 Ubuntu16 04 驱动版
  • 24种设计模式之单例模式(饿汉式、懒汉式)

    一 单例模式 单例模式 Singleton Pattern 是指确保一个类在任何情况下都绝对只有一个实例 并提供一个全局访问点 单例模式是创建型模式 单例模式在现实生活中应用也非常广泛 例如 总统 班主任等 J2EE标准中的ServletC
  • 理解SPDX

    SPDX The Software Package Data Exchange SPDE an open standard for communicating software bill of material information in
  • 基于RFID技术在物流仓储中的解决方案—铨顺宏FUWIT

    一 行业背景 2011年6月8日国务院出台物流行业新国八条 明确指出要推进物流技术创新和应用 加强物流新技术自主研发 加快仓储物流设备研制 制定和推广物流标准 适时启动物联网的应用示范 推进物流信息资源开放共享 物流信息化 指在物流活动中全
  • 基于Opencv的水位识别,液面识别、高度识别

    Update 代码已经上传到github上了 可以点这里 Cutting 一直说这要整理一下Computer Vision课程的大作业 拖了好久 这两天忙着写一个订单处理的第三方库 陷入了僵局 所以换个口味 把大作业整理一下 Require
  • python入门到精通 _7异常、模块与包

    文章目录 1 异常捕获 1 1 捕获常规异常 1 2 捕获指定异常 1 3 捕获多个异常 1 4 异常的finally 2 模块的导入与自定义 2 1 模块的导入 2 2 模块的自定义 3 安装第三方包与自定义 3 1 自定义包 3 2 安
  • 生成3d地图obj(可导入到ppt中使用)

    一 效果 二 使用 1 网址 https 3d mapper com MAP index php 2 注册 3 使用 创建3D地图 正在生成中 有以下设置功能 截图 管理你的地图
  • 按键松手检测 - 检测是否连续按下

    u8 KEY Scan void static u8 keyup 1 防止检测多次 if keyup KEY0 0 KEY1 0 KEY3 0 delay ms 50 去抖 if KEY0 0 KEY1 0 KEY3 0 keyup 0 i
  • 代码质量有哪些评判标准?

    描述代码质量的词 灵活性 flexibility 可扩展性 extensibility 可维护性 maintainability 可读性 readability 可理解性 understandability 易修改性 changeabili
  • Kruskal算法代码实现

    package com kruskal import java util Arrays public class KruskalCase private int edgeNum 边的个数 private char vertexs 顶点个数