克鲁斯卡尔(Kruskal)算法

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

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

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

克鲁斯卡尔算法在所有连接森林的两个不同树的边里面,寻找权值最小的边将最小的边加入一个不相交的集合来进行维护,每次加入时判断该边的起始顶点与结束顶点是否属于同一个树,即是否使森林产生回路,如果不产生回路则加入集合

其对应伪代码如下:


其算法描述:
1-3 行将集合A初始化一个空集合,创建一棵树V;
4 行 对邻边进行排序
5-8行 循环对边按权重从低到高进行检查,从每条边的起点和终点进行检查,判断是否构成回路,没有形成回路则将边加入集合中

要点: 对边排序;判断是否形成回路;若没有回路则每次选择权值最小的边加入集合—这里体现了贪心算法的思想;

举例说明

1 选取权值最小的E-F边加入集合,E-F第一次加入肯定不会存在回路

2 选择权值第二小的C-D边放入集合,检查是否形成回路

3 选取D-E加入集合

4 当选取较小的边C-E时,发现C-D-E在集合中会形成回路,所以C-E不能加入集合
判断回路其实也简单:循环集合,从C-E边的起始顶点C和终点E出发,如果形成回路则
顶点C和顶点E必然共用同一终点。

5 重复 1 2 3 4 将B-F E-G A-B加入集合,最小生成树构建完成

代码实现

我们使用邻接表构建图

 class  Graph<T>{int vertexNum;int edgeNum;ArrayList< Edge<T>>  edgesList ;ArrayList< Vertex<T>> vertexList;public Graph(T[] vertex){vertexList = new ArrayList<>();edgesList = new ArrayList<>();this.addVertex(vertex);}static class Vertex<T> {T verName;//节点存储的内容Edge<T> edgeLink ;//顶点的边链public  Vertex(T name){verName = name;edgeLink = null;}@Overridepublic String toString() {return "Vertex{" +"verName=" + verName +'}';}}static class Edge<T> {Vertex<T> start;//边的头节点Vertex<T> end;//边的尾部节点int weight;//边的权值Edge<T> broEdge;// 节点连接的其他边,指向下一个邻接点public Edge(Vertex<T> start, Vertex<T> end,int weight){this.start = start;this.end = end;this.weight = weight;}@Overridepublic String toString() {return "Edge{" +"start=" + start +", end=" + end +", weight=" + weight +'}';}}public void addVertex(T[] vertex){for (T c : vertex) {vertexList.add(new Vertex<>(c));}vertexNum = vertex.length;}public  void  addEdge(T start,T end,int weight){Vertex<T> startVertex = getVertex(start);Vertex<T> endVertex = getVertex(end);edgesList.add(concatEdge(startVertex, endVertex,weight));concatEdge(endVertex, startVertex,weight);edgeNum++;}private  Edge<T> concatEdge(Vertex<T> startVertex, Vertex<T> endVertex, int weight){Edge<T> edge = new Edge<>(startVertex,endVertex,weight);if (startVertex.edgeLink != null){Edge<T> broEdge = startVertex.edgeLink;while (broEdge.broEdge != null){broEdge = broEdge.broEdge;}broEdge.broEdge = edge;}else{startVertex.edgeLink = edge;}return edge;}public   Vertex<T> getVertex(T verName){return vertexList.stream().filter(e -> e.verName.equals(verName)).findFirst().orElseThrow(()->new NoSuchElementException(verName+" is no present"));}
}

求解最小生成树

 public  LinkedList<Graph.Edge<Character>> kruskal(Graph<Character> graph){ArrayList<Graph.Edge<Character>> edgesList = graph.edgesList;edgesList.sort(Comparator.comparingInt(o -> o.weight));LinkedList<Graph.Edge<Character>> minTree = new LinkedList<>();int[] ends = new int[graph.edgeNum]; //用于保存"已有最小生成树" 中的每个顶点在最小生成树中的终点for (Graph.Edge<Character> edge : edgesList) {int p1 = getIndex(graph.vertexList, edge.start);int p2 = getIndex(graph.vertexList, edge.end);//获取p1这个顶点在已有最小生成树中的终点int m = loop(ends, p1);//获取p2这个顶点在已有最小生成树中的终点int n = loop(ends, p2);if (m != n) {minTree.add(edge);ends[m] = n;//将该边的起始顶点和终点进行连接,代表该边已经在最小生成树里}}return minTree;}private int loop(int[] ends, int i ) {while (ends[i] != 0) {i = ends[i];}return i;}private int getIndex(ArrayList<Graph.Vertex<Character>> vertexList,Graph.Vertex<Character> vertex ) {for(int i = 0; i < vertexList.size(); i++) {if(vertexList.get(i) == vertex) {return i;}}return -1;}

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

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

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

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

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

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

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

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

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

  5. 一文带你弄懂普里姆(Prim)算法和克鲁斯卡尔(Kruskal)算法

    Prim算法 Prim算法用于构造最小生成树,且适用于稠密图. 基本思想 : 归并顶点 设连通网络 N = { V, E } 从某顶点 u0 出发, 选择与它关联的具有最小权值的边(u0, v), 将 ...

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

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

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

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

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

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

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

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

最新文章

  1. 文本域textarea 的值也是用value 来表示的。
  2. 前端含金量较高的网站推荐
  3. 华硕计算机用户名默认,华硕路由器后台默认网址是多少
  4. 计算机二级c语言选择题范围,计算机二级C语言考点选择结构
  5. 10-300-020-简介-架构-简介
  6. 安卓开发者必备的六个工具
  7. python自动化上传文件_python接口自动化测试二十三:文件上传
  8. [藏]常用的匹配正则表达式和实例
  9. 【POJ 3348】Cows【凸包裸题】
  10. 【附源码】计算机毕业设计SSM汽车租赁系统
  11. pr开放式字幕(同步台词)
  12. 定位推送分享轻社交网络平台《足迹》——数据库设计
  13. SaaS 前世今生:老树开新花
  14. h0206. 区间选点
  15. Dell H310配置no-raid直通模式
  16. Linux如何设置网络唤醒
  17. Spark(火花)快速、通用的大数据处理引擎框架
  18. Vue+vant 直播间 - 在离开直播间时弹出确认框
  19. Postgresql中的sync相关参数源码分析
  20. 阿里云服务器环境配置

热门文章

  1. 全国青少年科技创新大赛全国青少年信息学奥林匹克系列比赛(大赛系列第12期)
  2. 基因芯片与NGS区别[转载]
  3. 【安全狐】NmapMasscan扫描工具使用详讲
  4. Win10/11 更改电脑用户名的方法
  5. python名片管理系统难点总结_Python学习笔记之名片管理系统
  6. 钙钛矿在太阳能电池领域的研究进展
  7. matplotlib 入门之Sample plots in Matplotlib
  8. 动画中的“表现手法”和“表现方式”分别是什么?今天艺点动画大家庭来给你唠嗑唠嗑
  9. SQL Server2019配置管理器无法连接到 WMI 提供程序
  10. sql数据库本地服务器不显示,sql数据库本地服务器不显示