Kruskal算法(java)
一、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)相关推荐
- 最小生成树 kruskal_使用Kruskal算法求解Java最小生成树问题
最小生成树 kruskal In Electronic Circuit we often required less wiring to connect pins together. We can m ...
- 贪婪算法在求解最小生成树中的应用(JAVA)--Kruskal算法
Kruskal算法又被称为"加边法",这种算法会将加权连通图的最小生成树看成具有V-1条边的无环子图,且边的权重和最小.算法开始时,会按照权重的非递减顺序对图中的边排序,之后迭代的 ...
- 【Java数据结构与算法】第十九章 贪心算法、Prim算法和Kruskal算法
第十九章 贪心算法.Prim算法和Kruskal算法 文章目录 第十九章 贪心算法.Prim算法和Kruskal算法 一.贪心算法 1.介绍 2.支付问题 二.Prim算法 1.最小生成树 2.介绍 ...
- kruskal java_Kruskal算法java版
/*** sample Kruskal.java Description: * kruskal算法的思想是找最小边,且每次找到的边不会和以找出来的边形成环路,利用一个一维数组group存放当前顶点所在 ...
- 克鲁斯卡尔kruskal算法(Java)
目录 第6章 克鲁斯卡尔算法 6.1 应用场景 6.2 算法介绍 6.3 图解算法 6.4代码实现 本次克鲁斯卡尔算法 的教程出自韩顺平的数据结构与算法 第6章 克鲁斯卡尔算法 6.1 应用场景 6. ...
- 【数据结构与算法】图结构最小生成树Kruskal算法的Java实现
Kruskal算法 Kruskal算法是图论中用于求解最小生成树的算法,算法时间复杂度为O(eloge) 比较起Prim算法,Kruskal算法虽然同求最小生成树,却更适合稀疏网. 这里图的储存结构建 ...
- Java实现之克鲁斯卡尔(Kruskal)算法
一.问题引入 1.问题引入 1)某城市新增7个站点(A,B,C,D,E,F,G),现在需要修路把7个站点连通 2)各个站点的距离用边线表示(权),比如A-B距离12公里 3)问:如何修路保证各个站点都 ...
- Java数据结构之克里斯卡尔算法(Kruskal算法)
介绍 Kruskal算法与Prim算法不同,Prim是以顶点为向导,通过遍历顶点不断寻找与之相连的最小的权值边,从而找到最小生成树.Kruskal算法是以边为向导,依次找出权值最小的边建立最小生成树, ...
- ds图—最小生成树_Java: Kruskal算法生成最小生成树(邻接矩阵)
Java: Kruskal算法生成最小生成树(邻接矩阵): package 输出: Kruskal=36: (E,F) (C,D) (D,E) (B,F) (E,G) (A,B) 分析: Java: ...
最新文章
- js 性能优化整理之 缓存变量
- 一个对象的属性_【前端冷知识】如何判断一个对象的某个属性是可写的?
- 什么材质耐酸碱_粘玻璃用什么胶水?选择高透明强力胶水不后悔!
- 浅谈PostgreSQL的索引
- python代码学习-数据处理图片加遮挡、噪声、模糊
- cadence导入dxf文件_DXF如何导入为图纸?
- 准备让MSN机器人可以显示头像
- CKeditor4.7.3标准版图片上传及相关配置
- 寄存器和存储器的区别_汇编语言 第二章 寄存器
- 【Win 10 应用开发】手写识别
- Atitit 反模式 黑名单 异常处理 反模式(antipatterns) 目录 1.1. 记录并抛出(log and throw)	1 1.2. 抛出异常基类(Throwing Excepti
- 射频芯片,最全介绍!
- Flexsim国外视频教程
- VLAN(虚拟局域网)
- 计算机考试outlook怎么发邮件,outlook怎么用,教您outlook使用方法
- yum源修改为本地光盘镜像
- 全球屏占比最高!华为MatePad Pro震撼发布
- JAVA-Swing技术
- UE4 Socket多线程非阻塞通信【2】
- SMARTS决策引擎使用手册(6)
热门文章
- JavaWeb项目smbms超市订单管理系统
- session共享问题
- 学习笔记(03):MySQL数据库从入门到搞定实战-DDL之数据表
- ambari全攻略流程,认识ambari(一)
- MySQL中from_unixtime和unix_timestamp处理数据库时间戳转换问题-案例
- 谷歌浏览器无法安装插件解决方法分享
- 班主任联合家长群推进高中生德育教育
- java切点配置_Spring AOP中定义切点的实现方法示例
- GPU Direct p2p、 Nvlink 、GPU DirectRDMA
- 计算机思维入门观后感怎么写,读《逻辑思维简易入门》后感