返回顶部
首页 > 资讯 > 后端开发 > Python >Java实现最小生成树MST的两种解法
  • 858
分享到

Java实现最小生成树MST的两种解法

2024-04-02 19:04:59 858人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

目录一、prim算法二、kruskal算法一、prim算法 时间复杂度较之kruskal较高 通俗的解释就是: (1)从哪个点开始生成最小生成树都一样,最后的权值都是相同的 (2

一、prim算法

时间复杂度较之kruskal较高

通俗的解释就是:

(1)从哪个点开始生成最小生成树都一样,最后的权值都是相同的

(2)从哪个点开始,先标记这个点是访问过的,用visited数组表示所有节点的访问情况

(3)访问节点开始都每个没访问结点的距离选取形成的边的权值最小值

综合以上三点就是我们prim算法写代码实现的重要思路

代码实现:

package Prim;
 
import java.util.Arrays;
 
public class PrimAlGorithm {
    public static void main(String[] args) {
        //测试看看图是否创建ok
        char[] data = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G'};
        int verxs = data.length;
        //邻接矩阵的关系使用二维数组表示,10000这个大数,表示两个点不联通
        int[][] weight = new int[][]{
                {10000, 5, 7, 10000, 10000, 10000, 2},
                {5, 10000, 10000, 9, 10000, 10000, 3},
                {7, 10000, 10000, 10000, 8, 10000, 10000},
                {10000, 9, 10000, 10000, 10000, 4, 10000},
                {10000, 10000, 8, 10000, 10000, 5, 4},
                {10000, 10000, 10000, 4, 5, 10000, 6},
                {2, 3, 10000, 10000, 4, 6, 10000},};
        MGraph mGraph = new MGraph(verxs);
        MinTree minTree = new MinTree();
        minTree.createGraph(mGraph, verxs, data, weight);
        minTree.showGraph(mGraph);
        minTree.Prim(mGraph, 0);
    }
}
 
class MinTree {
    
    public void createGraph(MGraph graph, int verxs, char[] data, int[][] weight) {
        int i, j;
        for (i = 0; i < verxs; i++) {
            graph.data[i] = data[i];
            for (j = 0; j < verxs; j++) {
                graph.weight[i][j] = weight[i][j];
            }
        }
    }
 
    // 显示图的邻接矩阵
    public void showGraph(MGraph graph) {
        for (int[] link : graph.weight) {
            System.out.println(Arrays.toString(link));
        }
    }
 
    
    public void Prim(MGraph graph, int v) {
        //定义一个数组,判断节点是不是被访问过了
        int[] visited = new int[graph.verxs];
        //v这个点已经被访问了,从这个点开始访问
        visited[v] = 1;
        //找到节点下标
        int h1 = -1;
        int h2 = -1;
        int minWeight = 10000;//定义初始值为最大值,只要出现小的就会替换
        int sum = 0;
        // 从1开始循环,相当于就是生成graph.verx - 1条边
        for (int k = 1; k < graph.verxs; k++) {
 
            for (int i = 0; i < graph.verxs; i++) {//遍历已经访问过的点
                if (visited[i] == 1){
                    for (int j = 0; j < graph.verxs; j++) {//遍历没有访问过的点
                        //在未访问点中寻找所有与访问过的点相连的边中权值最小值
                        if (visited[i] == 1 && visited[j] == 0 && graph.weight[i][j] < minWeight) {
                            minWeight = graph.weight[i][j];
                            h1 = i;
                            h2 = j;
                        }
                    }
                }
            }
            sum += minWeight; // 求最小生成熟的总权值
            //此时已经找到一条边是最小了
            System.out.println("边<" + graph.data[h1] + "," + graph.data[h2] + "> 权值:" + minWeight);
            //然后标记点
            visited[h2] = 1;
            //将权值重新变成最大值
            minWeight = 10000;
        }
        System.out.println("最小生成树的权值是:" + sum);
 
    }
}
 
// 图
class MGraph {
    int verxs; // 表示图节点个数
    char[] data; // 表示节点数据
    int[][] weight; // 表示边
 
    public MGraph(int verxs) {
        this.verxs = verxs;
        data = new char[verxs];
        weight = new int[verxs][verxs];
    }
}

二、kruskal算法

时间复杂度低一些,但是代码量会大一些

对克鲁斯卡尔算法的通俗解释:

(1)对每条边的权值进行排序

(2)按照从小到大依次选取边构成最小生成树,但是要注意是否构成回路,树的概念是不能生成回路

(3)此处用的方法比较巧妙使用了getEnd方法来判断两者终点是不是一样,用ends数组保存最小生成树中每个顶点的终点

代码实现:

package Kruskal;
 
import java.util.Arrays;
 
public class KruskalCase {
 
    private int edgeNum; //边的个数
    private char[] vertexs; //顶点数组
    private int[][] matrix; //邻接矩阵
    //使用 INF 表示两个顶点不能连通
    private static final int INF = Integer.MAX_VALUE;
 
    public static void main(String[] args) {
        char[] vertexs = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
        //克鲁斯卡尔算法的邻接矩阵
        int matrix[][] = {
                
                 {0, 12, INF, INF, INF, 16, 14},
                 {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 kruskalCase = new KruskalCase(vertexs, matrix);
        //输出构建的
        kruskalCase.print();
        kruskalCase.kruskal();
 
    }
 
    //构造器
    public KruskalCase(char[] vertexs, int[][] matrix) {
        //初始化顶点数和边的个数
        int vlen = vertexs.length;
 
        //初始化顶点, 复制拷贝的方式
        this.vertexs = new char[vlen];
        for (int i = 0; i < vertexs.length; 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 (this.matrix[i][j] != INF) {
                    edgeNum++;
                }
            }
        }
 
    }
 
    public void kruskal() {
        int index = 0; //表示最后结果数组的索引
        int[] ends = new int[edgeNum]; //用于保存"已有最小生成树" 中的每个顶点在最小生成树中的终点
        //创建结果数组, 保存最后的最小生成树
        EData[] rets = new EData[edgeNum];
 
        //获取图中 所有的边的集合 , 一共有12边
        EData[] edges = getEdges();
        System.out.println("图的边的集合=" + Arrays.toString(edges) + " 共" + edges.length); //12
 
        //按照边的权值大小进行排序(从小到大)
        sortEdges(edges);
 
        //遍历edges 数组,将边添加到最小生成树中时,判断是准备加入的边否形成了回路,如果没有,就加入 rets, 否则不能加入
        for (int i = 0; i < edgeNum; i++) {
            //获取到第i条边的第一个顶点(起点)
            int p1 = getPosition(edges[i].start); //p1=4
            //获取到第i条边的第2个顶点
            int p2 = getPosition(edges[i].end); //p2 = 5
 
            //获取p1这个顶点在已有最小生成树中的终点
            int m = getEnd(ends, p1); //m = 4
            //获取p2这个顶点在已有最小生成树中的终点
            int n = getEnd(ends, p2); // n = 5
            //是否构成回路
            if (m != n) { //没有构成回路
                ends[m] = n; // 设置m 在"已有最小生成树"中的终点 <E,F> [0,0,0,0,5,0,0,0,0,0,0,0]
                rets[index++] = edges[i]; //有一条边加入到rets数组
            }
        }
        //<E,F> <C,D> <D,E> <B,F> <E,G> <A,B>。
        //统计并打印 "最小生成树", 输出  rets
        System.out.println("最小生成树为");
        for (int i = 0; i < index; i++) {
            System.out.println(rets[i]);
        }
 
 
    }
 
    //打印邻接矩阵
    public void print() {
        System.out.println("邻接矩阵为: \n");
        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();//换行
        }
    }
 
    
    private void sortEdges(EData[] edges) {
        for (int i = 0; i < edges.length - 1; i++) {
            for (int j = 0; j < edges.length - 1 - i; j++) {
                if (edges[j].weight > edges[j + 1].weight) {//交换
                    EData tmp = edges[j];
                    edges[j] = edges[j + 1];
                    edges[j + 1] = tmp;
                }
            }
        }
    }
 
    
    private int getPosition(char ch) {
        for (int i = 0; i < vertexs.length; i++) {
            if (vertexs[i] == ch) {//找到
                return i;
            }
        }
        //找不到,返回-1
        return -1;
    }
 
    
    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;
    }
 
    
    private int getEnd(int[] ends, int i) { // i = 4 [0,0,0,0,5,0,0,0,0,0,0,0]
        while (ends[i] != 0) {
            i = ends[i];
        }
        return i;
    }
 
}
 
//创建一个类EData ,它的对象实例就表示一条边
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;
    }
 
    //重写toString, 便于输出边信息
    @Override
    public String toString() {
        return "EData [<" + start + ", " + end + ">= " + weight + "]";
    }
 
 
}

到此这篇关于Java实现最小生成树MST的两种解法的文章就介绍到这了,更多相关Java最小生成树内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Java实现最小生成树MST的两种解法

本文链接: https://lsjlt.com/news/149811.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Java实现最小生成树MST的两种解法
    目录一、prim算法二、kruskal算法一、prim算法 时间复杂度较之kruskal较高 通俗的解释就是: (1)从哪个点开始生成最小生成树都一样,最后的权值都是相同的 (2...
    99+
    2024-04-02
  • Java求最小生成树的两种算法详解
    目录1 最小生成树的概述2 普里姆算法(Prim)2.1 原理2.2 案例分析3 克鲁斯卡尔算法(Kruskal)3.1 原理3.2 案例分析4 邻接矩阵加权图实现5 邻接表加权图实...
    99+
    2024-04-02
  • Java实现最小生成树算法详解
    目录定义带权图的实现Kruskal 算法二叉堆并查集实现算法Prim 算法定义 在一幅无向图G=(V,E) 中,(u,v) 为连接顶点u和顶点v的边,w(u,v)...
    99+
    2024-04-02
  • 浅谈算法之最小生成树Kruskal的Python实现
    目录一、前言二、树是什么三、从图到树四、解决生成问题五、从生成树到最小生成树六、实际问题与代码实现七、结尾一、前言 我们先不讲算法的原理,也不讲一些七七八八的概念,因为对于初学者来说,看到这些术语和概念往往会很头疼。...
    99+
    2022-06-02
    Python 最小生成树 Python Kruskal
  • Java 讲解两种找二叉树的最近公共祖先的方法
    目录思路一:先假设这棵树是二叉搜索树思路二:假设该树是用孩子双亲表示法思路一:先假设这棵树是二叉搜索树 首先我们补充说明一下什么是二叉搜索树: 在二叉搜索树中,对于每一个节点来说,他...
    99+
    2024-04-02
  • java生成随机字符串的两种方法
    本文实例为大家分享了java生成随机字符串的具体代码,供大家参考,具体内容如下import java.util.Random;public class CharacterUtils {//方法1:length为产生的位数 public s...
    99+
    2023-05-31
    java 字符串 ava
  • Python实现两种稀疏矩阵的最小二乘法
    目录最小二乘法返回值测试最小二乘法 scipy.sparse.linalg实现了两种稀疏矩阵最小二乘法lsqr和lsmr,前者是经典算法,后者来自斯坦福优化实验室,据称可以比lsqr...
    99+
    2023-02-26
    Python稀疏矩阵最小二乘法 Python稀疏矩阵 Python 最小二乘法
  • 详解Java递归实现树形结构的两种方式
    目录0、引言1、数据准备2、类型转化3、递归实现方法3.1、Java7及以下纯Java递归实现3.2、Java8及以上借助lamda表达式实现0、引言 在开发的过程中,很多业务场景需...
    99+
    2022-11-13
    Java递归实现树形结构 Java树形结构 Java递归
  • java图论普利姆及克鲁斯卡算法解决最小生成树问题详解
    目录什么是最小生成树?普利姆算法 算法介绍应用 --> 修路问题 图解分析 克鲁斯卡尔算法算法介绍应用场景 -- 公交站问题 算法图解 算法分析 如何判断是否构成回路代码实现 ...
    99+
    2024-04-02
  • Python如何实现两种稀疏矩阵的最小二乘法
    今天小编给大家分享一下Python如何实现两种稀疏矩阵的最小二乘法的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。最小二乘法s...
    99+
    2023-07-05
  • JAVA递归生成树形菜单的实现方法是什么
    今天小编给大家分享一下JAVA递归生成树形菜单的实现方法是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。  递归生成一个...
    99+
    2023-06-26
  • Java实现Excel转PDF的两种方法详解
    目录一、使用spire转化PDF1、使用spire将整个Excel文件转为PDF2、指定单个的sheet页转为PDF二、使用jacob实现Excel转PDF(推荐使用)1、环境准备2...
    99+
    2024-04-02
  • JAVA递归生成树形菜单的实现过程
      递归生成一个如图的菜单,编写两个类数据模型Menu、和创建树形的MenuTree。通过以下过程实现:     1.首先从菜单数据中获取所有根节点。     2.为根节点建立次级子...
    99+
    2024-04-02
  • C语言详细分析贪心策略中最小生成树的Prime算法设计与实现
    目录浅析最小生成树Prime算法思想此算法核心部分结构体的选择实现思路构造实例构造过程代码详解调试结果总结浅析最小生成树 设G=(V,E)是无向连通带权图。E中每条边(v,w)的权为...
    99+
    2024-04-02
  • python机器学习MATLAB最小二乘法的两种解读
    目录最小二乘法代价函数与最小二乘法向量到子空间的距离与最小二乘法最小二乘法与多项式拟合多项式拟合结果绘图:最小二乘法与多元线性回归多元线性回归结果绘图:最小二乘法 大部分的最小二乘法...
    99+
    2024-04-02
  • js将列表组装成树结构的两种实现方式分享
    目录前言背景介绍实现方案递归法资源总结前言 工作中偶尔就会遇到后端同学丢来一个列表,要我们自己组装成一个树结构渲染到页面上,本文以两种不同方式探索生成树的算法思想。 背景介绍 可组...
    99+
    2024-04-02
  • Java生成二维码的几种实现方式
    前言 本文将基于Spring Boot介绍两种生成二维码的实现方式,一种是基于Google开发工具包,另一种是基于Hutool来实现; 下面我们将基于Spring Boot,并采用两种方式实现二维码的...
    99+
    2023-09-06
    java 开发语言
  • java 中ArrayList迭代的两种实现方法
    java 中ArrayList迭代的两种实现方法Iterator与for语句的结合来实现,代码很简单,大家参考下。实现代码:package cn.us; import java.util.ArrayList; import java.uti...
    99+
    2023-05-31
    java arraylist 迭代
  • 基于Java数组实现循环队列的两种方法小结
    用java实现循环队列的方法:1、添加一个属性size用来记录眼下的元素个数。目的是当head=rear的时候。通过size=0还是size=数组长度。来区分队列为空,或者队列已满。2、数组中仅仅存储数组大小-1个元素,保证rear转一圈之...
    99+
    2023-05-30
    java 数组 循环队列
  • Java保留两位小数的实现方法
     Java保留两位小数的实现方法采用四舍五入的方式 : 该方式来自网络import java.math.BigDecimal;import java.text.DecimalFormat;import java.text.Numb...
    99+
    2023-05-31
    java 两位小数 ava
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作