一.问题引入

1.问题引入

1)某城市新增7个站点(A,B,C,D,E,F,G),现在需要修路把7个站点连通

2)各个站点的距离用边线表示(权),比如A-B距离12公里

3)问:如何修路保证各个站点都能连通,并且总的修建公路总里程最短?

二.克鲁斯卡尔算法

1.基本介绍

1)克鲁斯卡尔(Kruskal)算法,是用来求加权连通图的最小生成树的算法。
2)基本思想:按照权值从小到大的顺序选择n-1条边,并确定这n-1条边不构成回路
3)具体做法:首先构造一个只含n个顶点的森林,然后依权值从小到大从连通网
中选择边加入到森林中,并使森林中不产生回路,直至森林变成一棵树为止

2.思路分析

在含有n个顶点的连通图中选择n-1条边,构成一棵极小连通子图,并使该连通子图中n-1条边上权值之和达到最小,则称其为连通网的最小生成树。

例如,对于如上图G4所示的连通网可以有多棵权值总和不相同的生成树。

第一步:

第二步:

第三步:

第四步:

第五步:

第六步:

3.问题分析

根据前面介绍的克鲁斯卡尔算法的基本思想和做法,我们能够了解到,克鲁斯卡尔算法重点需要解决的以下两个问题:
问题一:对图的所有边按照权值大小进行排序。
问题二:将边添加到最小生成树中时,怎么样判断是否形成了回路。问题一很好解决,采用排序算法进行排序即可。
问题二的处理方式是:记录顶点在"最小生成树"中的终点,顶点的终点是"在最小生成树中与它连通的最大顶点"。然后每次需要将一条边添加到最小生存树时,判断该边的两个顶点的终点是否重合,重合的话则会构成回路。

4.判断构成回路图解

在将<E,F><C,D><D,E>加入到最小生成树R中之后,这几条边的顶点就都有了终点:
(01)C的终点是F。

(02)D的终点是F。

(03)E的终点是F。

(04)F的终点是F。

关于终点的说明:
1)就是将所有顶点按照从小到大的顺序排列好之后;某个顶点的终点就是"与它连通的最大顶点"。
2)因此,接下来,虽然<C.E>是权值最小的边。但是C和E的终点都是F,即
它们的终点相同,因此,将<C,E>加入最小生成树的话,会形成回路,这就是判断回路的方式.也就是说,我们加入的边的两个顶点不能都指向同一个终点,否则将构成回路。

5.代码实现

public class Kruskal {public int edgeNum; //边的个数public char[] vertex; //顶点数组public int[][] matrix; //public static void main(String[] args) {char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};int[][] matrix = new int[][]{{0, 12, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 16, 14},{12, 0, 10, Integer.MAX_VALUE, Integer.MAX_VALUE, 7, Integer.MAX_VALUE},{Integer.MAX_VALUE, 10, 0, 3, 5, 6, Integer.MAX_VALUE},{Integer.MAX_VALUE, Integer.MAX_VALUE, 3, 0, 4, Integer.MAX_VALUE, Integer.MAX_VALUE},{Integer.MAX_VALUE, Integer.MAX_VALUE, 5, 4, 0, 2, 8},{16, 7, 6, Integer.MAX_VALUE, 2, 0, 9},{14, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 8, 9, 0}};Kruskal kruskal = new Kruskal(vertex, matrix);kruskal.showGraph();System.out.println(kruskal.edgeNum);EdgeData[] edges = kruskal.getEdges();kruskal.sortEdges(edges);for (EdgeData edge : edges) {System.out.println(edge);}System.out.println("------------------------");kruskal.kruskal();}public Kruskal(char[] vertex, int[][] matrix) {//初始化顶点数和边的个数this.vertex = vertex;this.matrix = matrix;//统计边的条数for (int i = 0; i < vertex.length; i++) {for (int j = i + 1; j < vertex.length; j++) {if (matrix[i][j] != Integer.MAX_VALUE)edgeNum++;}}}public void showGraph() {for (int i = 0; i < vertex.length; i++) {for (int j = 0; j < vertex.length; j++) {System.out.printf("%-12d", matrix[i][j]);}System.out.println();}}//对边进行排序处理public void sortEdges(EdgeData[] edges) {Arrays.sort(edges);}//返回顶点的下标,如'A'-->0,找不到返回-1public int getPosition(char c) {for (int i = 0; i < vertex.length; i++) {if (c == vertex[i]) {return i;}}return -1;}//获取到图中的边,放到EdgeData[]数组中,通过int[][] matrix获取public EdgeData[] getEdges() {int index = 0;EdgeData[] edges = new EdgeData[edgeNum];for (int i = 0; i < vertex.length; i++) {for (int j = i + 1; j < vertex.length; j++) {if (matrix[i][j] != Integer.MAX_VALUE) {edges[index++] = new EdgeData(vertex[i], vertex[j], matrix[i][j]);}}}return edges;}/*** 功能:获取下标为i的顶点的终点,用于后面判断两个顶点的终点是否相等** @param ends 数组记录了各个顶点的终点,ends数组是在遍历过程中逐渐形成的* @param i* @return 返回下标为i的终点*/public int getEnd(int[] ends, int i) {while (ends[i] != 0) {i = ends[i];}return i;}//public void kruskal() {int index = 0;int[] ends = new int[edgeNum];//表示已有生成树//创建结果数组,保存最小生成树ArrayList<EdgeData> result = new ArrayList<>();//获取图中所有边的集合EdgeData[] edges = getEdges();//按照权值,从小到大排序sortEdges(edges);//遍历edges数组,将边添加到最小生成树,并判断是否构成回路,如果没有,就加入for (int i = 0; i < edgeNum; i++) {//获取第i条边的起点int start = getPosition(edges[i].start);//获取第i条边的终点int end = getPosition(edges[i].end);//获取start顶点在最小生成树的终点int end1 = getEnd(ends, start);//获取end顶点在最小生成树的终点int end2 = getEnd(ends, end);//判断是否构成回路if (end1 != end2) {//没有构成回路ends[end1] = end2;result.add(edges[i]);//此边加入到数组中}}//输出最小生成树System.out.println(result);}}class EdgeData implements Comparable<EdgeData> {char start;  //边的起点char end;//边的终点int weight;  //边的权值public EdgeData(char start, char end, int weight) {this.start = start;this.end = end;this.weight = weight;}@Overridepublic String toString() {return "EdgeData{" +"<" + start +", " + end +"> weight=" + weight +'}';}@Overridepublic int compareTo(EdgeData o) {return this.weight - o.weight;}
}

Java实现之克鲁斯卡尔(Kruskal)算法相关推荐

  1. 算法:通过克鲁斯卡尔(Kruskal)算法,求出图的最小生成树

    之前我给大家分享过用普利姆(Prim)算法来求出图的最小生成树(点我去看看),今天我再给大家分享一个也是求图的最小生成树的克鲁斯卡尔(Kruskal)算法 克鲁斯卡尔(Kruskal)算法,就相当于先 ...

  2. 【算法】克鲁斯卡尔 (Kruskal) 算法

    目录 1.概述 2.代码实现 2.1.并查集 2.2.邻接矩阵存储图 2.3.邻接表存储图 2.4.测试代码 3.应用 本文参考: <数据结构教程>第 5 版 李春葆 主编 1.概述 (1 ...

  3. 【数据结构与算法】克鲁斯卡尔(Kruskal)算法

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

  4. 数据结构与算法(7-3)最小生成树(普里姆(Prim)算法和克鲁斯卡尔(Kruskal)算法)

    目录 一.最小生成树简介 二.普里姆算法(Prim) 1.原理 2.存储 2-1.图顶点和权: 2-3. 最小生成树: 3.Prim()函数 3-1.新顶点入树 3-2.保留最小权 3-3. 找到最小 ...

  5. 对下图所示的连通网络G,用克鲁斯卡尔(Kruskal)算法求G的最小生成树T,请写出在算法执行过程中,依次加入T的边集TE中的边。说明该算法的基本思想及贪心策略,并简要分析算法的时间复杂度

    对下图所示的连通网络G,用克鲁斯卡尔(Kruskal)算法求G的最小生成树T,请写出在算法执行过程中,依次加入T的边集TE中的 边.说明该算法的基本思想及贪心策略,并简要分析算法的时间复杂度

  6. 算法之克鲁斯卡尔(Kruskal)算法

    克鲁斯卡尔(Kruskal)算法 克鲁斯卡尔(Kruskal)算法,是用来求加权连通图的最小生成树的算法. 基本思想:按照权值从小到大的顺序选择n-1条边,并保证这n-1条边不构成回路 具体做法:首先 ...

  7. 普里姆(Prim)算法和克鲁斯卡尔(Kruskal)算法

    图是一种基础又重要的数据结构,图的生成树是图的一个极小连通子图.最小生成树是无向连通网的所有生成树中边的权值之和最小的一棵生成树.求图的最小生成树可以牵引出很多经典的题目,例如在N个城市之间建立通讯网 ...

  8. 普里姆算法(Prim)和克鲁斯卡尔(Kruskal)算法

    普里姆算法(Prim)和克鲁斯卡尔(Kruskal)算法 普里姆算法的基本思想: 取图中任意一个顶点 v 作为生成树的根,之后往生成树上添加新的顶点 w.添加顶点w的条件为:w 和已在生成树上的顶点v ...

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

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

最新文章

  1. Linux--------------安装jdk
  2. 【My Project】数字频率测量FPGA实现
  3. 信息系统状态过程图_操作系统中的增强型过程状态图
  4. excel在线_功能强大的纯前端 Excel 在线表格: Luckysheet
  5. android word设计模式,word07设计模式
  6. cass读取dat文件_南方CASS教程+视频讲解+插件汇总,小白快速上手的测绘神器
  7. 基于JAVA+SpringMVC+Mybatis+MYSQL的会员管理系统
  8. 小苹果 html,定时轮播.html
  9. Rational ClearCase批量merge合并
  10. 人人网主页登录_人人网回归了!历史记录全保留!前男(女)友们的黑历史就要被重新翻开了...
  11. 文件服务器mfs,分布式文件系统MFS(moosefs)实现存储共享
  12. 督办管理系统——让企业工作落实到位
  13. 小学文凭宝妈在家开网店?其实做跨境并不难!
  14. 大型会议的礼仪(2)
  15. Vue调用手机相机和相册以及上传
  16. 怎么设置桌面提醒任务,好用的桌面便签提醒工具
  17. 异步工作 boost asio
  18. 短链有啥好处,用长链不香吗
  19. 74、常见的几种网络故障案例分析与解决
  20. 微信答题抢红包小程序实现思路

热门文章

  1. 关于人生,理想和抉择的对话
  2. 关于MacBook Pro外接显示器飞利浦279C9,用全功能type-C连接无法达到4K60hz的问题
  3. [我可怜的3110c!nbsp;续]
  4. 程立新:中兴手机要做消费者无法拒绝的产品
  5. DDR2 IP核地址总线解疑
  6. DECLARE_HANDLE()
  7. 大猫猫的JNCIE考试经历-第一次Fail
  8. 关于HSV了解这些就够了,python-opencv获取图片精确hsv的值
  9. winForm ImageList图像控件使用
  10. C++对象数组的使用