提出问题

基本介绍

克鲁斯卡尔(Kruskal)算法,求加权连通图最小生成树的算法

基本思想:按权值从小到大顺序选择n-1条边,保证n-1条边不够成回路

具体做法:先构造一个只有n顶点的森林,然后按权值从小到大连通网中选择边加入森林中,保证森林不产生回路,直到森林变为一棵树为止

图解算法

这里5和6的权值的边都不选是因为选了会构成回路

问题1:对图中的所有边按照权值大小进行排序。
解决办法:采用排序算法进行排序即可

问题2:将边添加到最小生成树中时,怎么样判断是否形成回路。
解决办法:记录顶点在“最小生成树”中的终点,顶点的终点是“在最小生成树中与它连通的最大顶点”。然后,每次需要将一条边添加到最小生成树时,判断该边的两个顶点的终点是否重合,重合的话则会构成回路。

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

  1. C的终点是F
  2. D的终点是F
  3. E的终点是F
  4. F的终点是F

关于终点的说明:

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

完整代码实现

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[][] = {/*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 = 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>。//统计并打印 "最小生成树", 输出  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;`在这里插入代码片`}//重写toString, 便于输出边信息@Overridepublic String toString() {return "EData [<" + start + ", " + end + ">= " + weight + "]";}}

数据结构与算法-克鲁斯卡尔算法(Kruskal) | 尚硅谷韩顺平相关推荐

  1. 数据结构——最小生成树之克鲁斯卡尔算法(Kruskal)

    最小生成树算法 prime算法和克鲁斯卡尔算法 克鲁斯卡尔算法 思路 优先队列+并查集 Kuskal算法 [算法简介]:上一篇中的Prime算法是一种"加点式的算法",而Kuska ...

  2. 【尚硅谷|韩顺平】数据结构和算法

    文章目录 前言: 数据结构和算法 数据结构和算法的概述 数据结构和和算法的关系 数据结构 线性结构和非线性结构 非线性结构 稀疏 sparsearray 数组 基本介绍: 稀疏数组的处理方法是: 应用 ...

  3. 【数据结构】图—克鲁斯卡尔算法(原理及C程序详解)

    普利姆(Prim)算法是以某个顶点为起点,逐步寻找各个顶点上权值最小的边来构建生成树. 文章指引:图-普里姆(Prim)算法(原理和C程序解释) 而克鲁斯卡尔(Kruskal)算法是以边为目标,直接寻 ...

  4. 常用的十种算法--克鲁斯卡尔算法

    1.克鲁斯卡尔算法应用场景: 使用克鲁斯卡尔算法生成最小生成树. 2.克鲁斯卡尔算法介绍:         克鲁斯卡尔算法的核心思想是:在带权连通图中,不断地在边集合中找到最小的边,如果该边满足得到最 ...

  5. 算法-克鲁斯卡尔算法

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

  6. 用c语言描述普里姆算法和克鲁斯卡尔算法,克鲁斯卡尔算法+普里姆算法 详解

    克鲁斯卡尔算法: [1]克鲁斯卡尔算法 普里姆算法是以某顶点为起点,逐步找各顶点上最小权值的边来构建最小生成树. 克鲁斯卡尔算法是直接以边为目标去构建. 因为权值是在边上,直接去找最小权值的边来构建生 ...

  7. 【数据结构与算法】尚硅谷韩顺平老师+含java代码(更新中)

    数据结构与算法 程序 = 数据结构 + 算法 数据结构:树.链表.图等 线性结构 数组.队列.链表和栈 非线性结构 二维数组,多维数组,广义表,树结构,图结构 稀疏数组 稀疏数组的好处时压缩数组 在这 ...

  8. 数据结构与算法-普利姆算法(Prim) | 尚硅谷韩顺平

    最小生成树 给定一个带权无向连通图,选取一棵树,让树所有边上权的总和最小,叫最小生成树 N个顶点,一定有N-1条边 包含全部顶点 N-1条边都要在图中 算法介绍 普里姆算法求最小生成树,也就是在包含n ...

  9. 算法 -克鲁斯卡尔算法

    如果形成回路则不选择 文字描述 加入的边的两个顶点不能都指向同一个终点,否则会构成回路

最新文章

  1. C#实现Base64编码与解码
  2. 【STM32】SPI相关函数和类型
  3. Redis Cluster原理初步
  4. 基于NFS实现lamp的负载均衡之二: 部署NFS服务器
  5. .Net性能调优-垃圾回收!!!最全垃圾回收来了
  6. 电子商务与计算机科学与技术的相关性,电子商务、计算机科学与技术、法学等相关专业。.doc...
  7. 图像 - 灰度化、灰度反转、二值化
  8. python字符串及基本运算
  9. 1203.1——条件语句 之 if语句
  10. mysql在windows配置多节点_Windows环境配置MySQL集群
  11. vue 生成qrCode二维码保存图片至本地
  12. session保存和清除cookies
  13. html 整个页面只能看,如何截图整个完整的网页页面(包含滚动条下面看不到的网页)...
  14. 【渝粤题库】国家开放大学2021春1108钢结构(本)题目
  15. 关于《火影忍者 博人传》的一点想法
  16. 不怕你不来,就怕你不学—360前端星计划
  17. 刷脸生物识别安全保障远大于传统安全保障
  18. 小白兔拔萝卜问题的递归求解
  19. 医疗智能BI助你建立智慧医院
  20. StandardServer.await: Invalid command 'GET /setting/webSocket HTTP/1.1' rece

热门文章

  1. 安卓开发——UI界面开发
  2. c语言求a b 最大公约数和最小公倍数,常见算法:C语言求最小公倍数和最大公约数三种算法...
  3. html中边框倒影怎么弄,巧用css3的-webkit-box-reflect 倒影属性实现各种特效
  4. 机原自检——第10章 齿轮机构及其设计
  5. 2018双11手机购买推荐
  6. 软件工程知识点汇总(期末总复习)
  7. 在软件设计前先画界面图
  8. c语言getline函数什么意思,getline函数(精华版)详解
  9. 强烈推荐 | 程序员七大生产力工具
  10. SomethingOn生产力提升工具使用