一、Kruskal算法介绍

  Kruskal算法是一种构造最小生成树的算法。时间复杂度为 O ( ∣ E ∣ l o g ∣ E ∣ ) O(|E|log|E|) O(∣E∣log∣E∣)。Kruskal算法适合于边稀疏而顶点较多的图。

二、Kruskal算法原理

  (1)初始时为只有n个顶点而无边的非连通图T,每个顶点自成一个连通分量。
  (2)按照边的权值由小到大的顺序,不断选取当前未被选取过且权值最小的边,若该边依附的顶点落在T中不同的连通分量上,则将此边加入T,否则舍弃此边而选择下一条权值最小的边。换句话说,加入的边不能连成环。
  (3)重复(2)步骤,直至T中所有顶点都在一个连通分量上。

三、Kruskal算法图解


  构造图(a)的最小生成树过程如下:
  (1)将边按权值大小排序:

< V 1 , V 3 V_{1},V_{3} V1​,V3​>:1
< V 4 , V 6 V_{4},V_{6} V4​,V6​>:2
< V 2 , V 5 V_{2},V_{5} V2​,V5​>:3
< V 3 , V 6 V_{3},V_{6} V3​,V6​>:4
< V 1 , V 4 V_{1},V_{4} V1​,V4​>:5
< V 2 , V 3 V_{2},V_{3} V2​,V3​>:5
< V 3 , V 4 V_{3},V_{4} V3​,V4​>:5
< V 1 , V 2 V_{1},V_{2} V1​,V2​>:6
< V 3 , V 5 V_{3},V_{5} V3​,V5​>:6
< V 5 , V 6 V_{5},V_{6} V5​,V6​>:6

  (2)首先,将< V 1 , V 3 V_{1},V_{3} V1​,V3​>加入最小生成树中。(如图b所示)
  (3)将< V 4 , V 6 V_{4},V_{6} V4​,V6​>加入最小生成树中。(如图c所示)
  (4)将< V 2 , V 5 V_{2},V_{5} V2​,V5​>加入最小生成树中。(如图d所示)
  (5)将< V 3 , V 6 V_{3},V_{6} V3​,V6​>加入最小生成树中。(如图e所示)
  (6)此时最小权值的边为:< V 1 , V 4 V_{1},V_{4} V1​,V4​>、< V 2 , V 3 V_{2},V_{3} V2​,V3​>、< V 3 , V 4 V_{3},V_{4} V3​,V4​>,由于< V 1 , V 4 V_{1},V_{4} V1​,V4​>、< V 3 , V 4 V_{3},V_{4} V3​,V4​>成环,所以将< V 2 , V 3 V_{2},V_{3} V2​,V3​>加入最小生成树中。(如图f所示)
  (7)边的数目=顶点数目-1,最小生成树构造完成。

四、Kruskal算法代码实现

package com.haiyang.algorithm.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[][] = {/*A*//*B*//*C*//*D*//*E*//*F*//*G*//*A*/ {   0,  12, INF, INF, INF,  16,  14},/*B*/ {  12,   0,  10, INF, INF,   7, INF},/*C*/ { INF,  10,   0,   3,   5,   6, INF},/*D*/ { INF, INF,   3,   0,   4, INF, INF},/*E*/ { INF, INF,   5,   4,   0,   2,   8},/*F*/ {  16,   7,   6, INF,   2,   0,   9},/*G*/ {  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 = vertexs;//初始化边, 使用的是复制拷贝的方式this.matrix = matrix;//统计边的条数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>。//统计并打印 "最小生成树", 输出  retsSystem.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();//换行}}/*** 功能:对边进行排序处理, 冒泡排序* @param edges 边的集合*/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;}}}}/**** @param ch 顶点的值,比如'A','B'* @return 返回ch顶点对应的下标,如果找不到,返回-1*/private int getPosition(char ch) {for(int i = 0; i < vertexs.length; i++) {if(vertexs[i] == ch) {//找到return i;}}//找不到,返回-1return -1;}/*** 功能: 获取图中边,放到EData[] 数组中,后面我们需要遍历该数组* 是通过matrix 邻接矩阵来获取* EData[] 形式 [['A','B', 12], ['B','F',7], .....]* @return*/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的顶点的终点(), 用于后面判断两个顶点的终点是否相同* @param ends : 数组就是记录了各个顶点对应的终点是哪个,ends 数组是在遍历过程中,逐步形成* @param i : 表示传入的顶点对应的下标* @return 返回的就是 下标为i的这个顶点对应的终点的下标,*/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;}@Overridepublic String toString() {return "EData [<" + start + ", " + end + ">= " + weight + "]";}}

Kruskal算法(java)相关推荐

  1. 最小生成树 kruskal_使用Kruskal算法求解Java最小生成树问题

    最小生成树 kruskal In Electronic Circuit we often required less wiring to connect pins together. We can m ...

  2. 贪婪算法在求解最小生成树中的应用(JAVA)--Kruskal算法

    Kruskal算法又被称为"加边法",这种算法会将加权连通图的最小生成树看成具有V-1条边的无环子图,且边的权重和最小.算法开始时,会按照权重的非递减顺序对图中的边排序,之后迭代的 ...

  3. 【Java数据结构与算法】第十九章 贪心算法、Prim算法和Kruskal算法

    第十九章 贪心算法.Prim算法和Kruskal算法 文章目录 第十九章 贪心算法.Prim算法和Kruskal算法 一.贪心算法 1.介绍 2.支付问题 二.Prim算法 1.最小生成树 2.介绍 ...

  4. kruskal java_Kruskal算法java版

    /*** sample Kruskal.java Description: * kruskal算法的思想是找最小边,且每次找到的边不会和以找出来的边形成环路,利用一个一维数组group存放当前顶点所在 ...

  5. 克鲁斯卡尔kruskal算法(Java)

    目录 第6章 克鲁斯卡尔算法 6.1 应用场景 6.2 算法介绍 6.3 图解算法 6.4代码实现 本次克鲁斯卡尔算法 的教程出自韩顺平的数据结构与算法 第6章 克鲁斯卡尔算法 6.1 应用场景 6. ...

  6. 【数据结构与算法】图结构最小生成树Kruskal算法的Java实现

    Kruskal算法 Kruskal算法是图论中用于求解最小生成树的算法,算法时间复杂度为O(eloge) 比较起Prim算法,Kruskal算法虽然同求最小生成树,却更适合稀疏网. 这里图的储存结构建 ...

  7. Java实现之克鲁斯卡尔(Kruskal)算法

    一.问题引入 1.问题引入 1)某城市新增7个站点(A,B,C,D,E,F,G),现在需要修路把7个站点连通 2)各个站点的距离用边线表示(权),比如A-B距离12公里 3)问:如何修路保证各个站点都 ...

  8. Java数据结构之克里斯卡尔算法(Kruskal算法)

    介绍 Kruskal算法与Prim算法不同,Prim是以顶点为向导,通过遍历顶点不断寻找与之相连的最小的权值边,从而找到最小生成树.Kruskal算法是以边为向导,依次找出权值最小的边建立最小生成树, ...

  9. ds图—最小生成树_Java: Kruskal算法生成最小生成树(邻接矩阵)

    Java: Kruskal算法生成最小生成树(邻接矩阵): package 输出: Kruskal=36: (E,F) (C,D) (D,E) (B,F) (E,G) (A,B) 分析: Java: ...

最新文章

  1. js 性能优化整理之 缓存变量
  2. 一个对象的属性_【前端冷知识】如何判断一个对象的某个属性是可写的?
  3. 什么材质耐酸碱_粘玻璃用什么胶水?选择高透明强力胶水不后悔!
  4. 浅谈PostgreSQL的索引
  5. python代码学习-数据处理图片加遮挡、噪声、模糊
  6. cadence导入dxf文件_DXF如何导入为图纸?
  7. 准备让MSN机器人可以显示头像
  8. CKeditor4.7.3标准版图片上传及相关配置
  9. 寄存器和存储器的区别_汇编语言 第二章 寄存器
  10. 【Win 10 应用开发】手写识别
  11. Atitit 反模式 黑名单 异常处理 反模式(antipatterns) 目录 1.1. 记录并抛出(log and throw) 1 1.2. 抛出异常基类(Throwing Excepti
  12. 射频芯片,最全介绍!
  13. Flexsim国外视频教程
  14. VLAN(虚拟局域网)
  15. 计算机考试outlook怎么发邮件,outlook怎么用,教您outlook使用方法
  16. yum源修改为本地光盘镜像
  17. 全球屏占比最高!华为MatePad Pro震撼发布
  18. JAVA-Swing技术
  19. UE4 Socket多线程非阻塞通信【2】
  20. SMARTS决策引擎使用手册(6)

热门文章

  1. JavaWeb项目smbms超市订单管理系统
  2. session共享问题
  3. 学习笔记(03):MySQL数据库从入门到搞定实战-DDL之数据表
  4. ambari全攻略流程,认识ambari(一)
  5. MySQL中from_unixtime和unix_timestamp处理数据库时间戳转换问题-案例
  6. 谷歌浏览器无法安装插件解决方法分享
  7. 班主任联合家长群推进高中生德育教育
  8. java切点配置_Spring AOP中定义切点的实现方法示例
  9. GPU Direct p2p、 Nvlink 、GPU DirectRDMA
  10. 计算机思维入门观后感怎么写,读《逻辑思维简易入门》后感