Kruskal算法(克鲁斯卡尔算法)

article/2025/11/10 19:27:43

Kruskal算法

Kruskal算法是一种用来查找最小生成树的算法,由Joseph Kruskal在1956年发表。用来解决同样问题的还有Prim算法和Boruvka算法等。三种算法都是贪心算法的应用。

概念解释

Kruskal算法定义:**先构造一个只含 n 个顶点、而边集为空的子图,把子图中各个顶点看成各棵树上的根结点,之后,从网的边集 E 中选取一条权值最小的边,若该条边的两个顶点分属不同的树,则将其加入子图,即把两棵树合成一棵树,反之,若该条边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。依次类推,直到森林中只有一棵树,也即子图中含有 n-1 条边为止。

最小生成树定义:一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。(可以由Kruskal算法或者prim算法求出来)

执行步骤:
第一步:在带权连通图中,将边的权值排序;
第二步:判断是否需要选择这条边(此时图中的边已按权值从小到大排好序)。判断的依据是边的两个顶点是否已连通,如果连通则继续下一条;如果不连通,那么就选择使其连通。
第三步:循环第二步,直到图中所有的顶点都在同一个连通分量中,即得到最小生成树。

图解Kruskal算法

[外链图片转存失败(img-SMyVUx2V-1562946282066)(img/1.png)]

首先将图中的所有的边按权值从小到大排序:
HG < (CI=GF) < (AB=CF) < GI < (CD=HI) < (AH=BC) < DE < BH < DF
接着,我们选择HG这条边,这样就将H和G这两个点加入到了已经找到的点的集合。如下图所示:

[外链图片转存失败(img-uZ2FLyHQ-1562946282068)(img/3.png)]

由于两个一样的权值的边存在,所以就可以随便选一条,但是需要做出判断。
判断的法则:
(1)当所选的边加入已找到边的集合时候,会不会形成回路。如果没有形成回路,那么就“准备”将其连通,在真正连通之前还需要做一次判断,判断这两个点是否已经加入到已找到点的集合中去了
(2)如果两个点都没有出现,则将这两个点都加入到集合中去
(3)如果其中有一个点已经出现在集合中,则将另一个没有出现过的点,加入到集合中去
(4)如果两个都有出现,则不需要加入。

[外链图片转存失败(img-RpZmzgTZ-1562946282070)(img/2.png)]

[外链图片转存失败(img-D3tpD4SM-1562946282074)(img/4.png)]

[外链图片转存失败(img-YpGFm3bz-1562946282076)(img/5.png)]

以上三步不会形成回路,所以可以直接连通。

[外链图片转存失败(img-c8DwVRU9-1562946282079)(img/6.png)]

在连接IG的时候,会形成回路,所以放弃连通。
如何判断的?注意听这里是算法实现的重点:
判断两个已经连接到第三个点的点,会不会连接。

[外链图片转存失败(img-L9NUaVwQ-1562946282080)(img/7.png)]

[外链图片转存失败(img-7HVtpbrO-1562946282095)(img/8.png)]

至此我们得到了一个最小生成树。所有的点都在一个连通分量上了。

注意点:排序和防止回路

排序的解决:很好解决

(1)、只能用图中有的边;
(2)、只能用掉|v|-1条边;
(3)、不能有回路。

kruskal和prim的比较:

kruskal适用于比较稀疏的图,因为他每次都是从最小的边开始查找。让森林合并为树

prim算法适用于变数比较多的图。让小树慢慢长大。

简单的例子:

[外链图片转存失败(img-68olnHfZ-1562946282096)(img/9.png)]

public class Kruskal2 {private Edge[] edges;private int edgeSize;public Kruskal2(int edgeSize) {this.edgeSize = edgeSize;edges = new Edge[edgeSize];createEdgeKruskal();}/*** 创建边的集合,从小到大*/private void createEdgeKruskal() {
//        Edge edge0 = new Edge(6, 7, 1);
//        Edge edge1 = new Edge(5, 6, 2);
//        Edge edge2 = new Edge(2, 8, 2);
//        Edge edge3 = new Edge(0, 1, 4);
//        Edge edge4 = new Edge(2, 5, 4);
//        Edge edge5 = new Edge(6, 8, 6);
//        Edge edge6 = new Edge(7, 8, 7);
//        Edge edge7 = new Edge(2, 3, 7);
//        Edge edge8 = new Edge(1, 2, 8);
//        Edge edge9 = new Edge(0,7 , 8);
//        Edge edge10 = new Edge(3, 4, 9);
//        Edge edge11 = new Edge(4, 5, 10);
//        Edge edge12 = new Edge(1, 7, 11);
//        Edge edge13 = new Edge(3, 5, 14);
//        Edge edge14 = new Edge(4, 5, 26);Edge edge0 = new Edge(0, 3, 1);Edge edge1 = new Edge(1, 2, 2);Edge edge2 = new Edge(0,1,3);Edge edge3 = new Edge(1, 3, 5);Edge edge4 = new Edge(2, 3, 8);edges[0] = edge0;edges[1] = edge1;edges[2] = edge2;edges[3] = edge3;edges[4] = edge4;
//        edges[5] = edge5;
//        edges[6] = edge6;
//        edges[7] = edge7;
//        edges[8] = edge8;
//        edges[9] = edge9;
//        edges[10] = edge10;
//        edges[11] = edge11;
//        edges[12] = edge12;
//        edges[13] = edge13;
//        edges[14] = edge14;}/*** kruskal算法创建最小生成树*/public void createMinSpanTreeKruskal() {// 定义一个一维数组,下标为连线的起点,值为连线的终点int[] parent = new int[edgeSize];for (int i = 0; i < edgeSize; i++) {parent[i] = 0;}int sum = 0;for (Edge edge : edges) {//6, 7, 1// 找到起点和终点在临时连线数组中的最后连接点int start = find(parent, edge.start);// 6 2int end = find(parent, edge.end); // 7 8// 通过起点和终点找到的最后连接点是否为同一个点,是则产生回环if (start != end) {// 没有产生回环则将临时数组中,起点为下标,终点为值parent[start] = end;System.out.println("访问到了节点:{" + start + "," + end + "},权值:" + edge.weight);sum += edge.weight;}}for (int i : parent) {System.out.println(i+",");}System.out.println("最小生成树的权值总和:" + sum);}/*** 获取集合的最后节点*/private int find(int parent[], int index) {
//    	System.out.println(parent[index]);while (parent[index] > 0) {index = parent[index];}return index;}/*** 连接顶点的边*/class Edge {private int start;private int end;private int weight;public Edge(int start, int end, int weight) {this.start = start;this.end = end;this.weight = weight;}}public static void main(String[] args) {Kruskal2 graphKruskal = new Kruskal2(5);graphKruskal.createMinSpanTreeKruskal();}}

http://chatgpt.dhexx.cn/article/VLW9QGuf.shtml

相关文章

KruskalAlgorithm(克鲁斯卡尔算法)

KruskalAlgorithm介绍 克鲁斯卡尔(Kruskal)算法&#xff0c;是用来求加权连通图的最小生成树的算法。基本思想&#xff1a;按照权值从小到大的顺序选择 n-1 条边&#xff0c;并保证这 n-1 条边不构成回路具体做法&#xff1a;首先构造一个只含 n 个顶点的森林&#xff0c;然后…

数据结构——克鲁斯卡尔(Kruskal)算法

克鲁斯卡尔算法是求连通网的最小生成树的另一种方法。与普里姆算法不同&#xff0c;它的时间复杂度为O&#xff08;eloge&#xff09;&#xff08;e为边数&#xff09;&#xff0c;适合于求边稀疏的网的最小生成树 。克鲁斯卡尔算法从另一途径求网的最小生成树。其基本思想是&a…

克鲁斯卡尔(Kruskal)算法(严蔚敏C语言)

克鲁斯卡尔算法(Kruskal) ​ 克鲁斯卡尔算法是求连通网的最小生成树的另一种方法。与普里姆算法不同&#xff0c;它的时间复杂度为O&#xff08;eloge&#xff09;&#xff08;e为网中的边数&#xff09;&#xff0c;所以&#xff0c;适合于求边稀疏的网的最小生成树 。 ——百…

4.《学会提问》

1.书中的观点 批判性思维会教你很多技能和态度&#xff0c;让你理性地找到对自己有意义的答案并为此感到自豪。批判性思维鼓励你倾听他人&#xff0c;向别人学习&#xff0c;同时掂量别人所说的话&#xff0c;看看它们的分量如何。如此&#xff0c;你将了解到我们必须要依赖他人…

如何提问——提问的艺术

转存失败重新上传取消https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/master/README-zh_CN.md

《提问的艺术》读书笔记

分享读《提问的艺术》的xmind总结&#xff0c;每周听一本书&#xff0c;打卡第一周

(转载) 提问的艺术

虽然这是老话常谈&#xff0c;但是最近的回答问题的过程中&#xff0c;有点感触。你问题问的好&#xff0c;问的准确&#xff0c;回答你的人才有积极性给你答复&#xff0c;这样你又可以更快的解决你的问题。好多人不知道如何提问&#xff0c;所以我打算把这篇老文章转过来置顶…

论程序员提问的艺术

最近工作比较忙&#xff0c;加上空闲时间大部分都是在维护开发【云狗AI】&#xff0c;所以也有一段时间没更新视频了&#xff0c;有不懂的&#xff0c;也可以问一下【云狗AI】以后我也会花更多的时间在维护这个项目中。争取给大家带来更好的体验。 主要是因为最近没发现什么特…

提问的艺术[转]

这是刚看到的 所以转一下 也是警示自己的伸手行为 原文&#xff1a;How To Ask Questions The Smart Way 译文链接&#xff1a;提问的艺术 作者&#xff1a; 艾瑞克.史蒂文.雷蒙德(Eric Steven Raymond) <esrthyrsus.com> 瑞克.莫恩(Rick Moen) <respond-autolinuxmaf…

【提问的艺术】

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 非常期待和您一起在这个小…

提问的艺术/怎么高效的提问

唉,可能是因为见过的人多了吧,不管是在现实世界中,还是在网络上,总是需要向别人询问一些东西的, 有的人来问,谦谦有礼,感觉很好,帮助了别人,也没损失什么,有的人来问,就是真心不想搭理他,搭理了他就是 浪费自己的时间,还心理不好受的. 今天不说现实中怎么提问.就说在互联网上.…

《提问的艺术》读后感

前言提问前 他明明能帮到我却不帮我提问前必知必会的一些事关于搜索引擎 提问时 找准对象学会停顿组织你的问题清晰的发问低声下气代替不了做自己的家庭作业删除无意义的要求不要把问题标记为紧急 即使对你而言的确如此礼貌总是有益的对待无礼提问禁区 总结 前言 众所周知&am…

提问的艺术,原文链接

你提的问题没有任何有用的信息&#xff0c;u hava a poop。 提问的艺术 今天在拉屎的时候看到QQ群里有人问问题&#xff0c;那个问题太他妈蠢了&#xff0c;所以我就写了这一片博客&#xff0c;如果再有人问愚蠢的问题我就把这篇博客丢给他。 提问的艺术 原文链接&#xff…

《提问的艺术:如何快速获得答案》(精读版)

《提问的艺术》《How-To-Ask-Questions-The-Smart-Way》 https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way © 2001 Eric Steve Raymond © 2001 D.H.Grand(nOBODY/Ginux) © 2012 Conmajia《提问的艺术&#xff1a;如何快速获得答案》原著Eric…

Serverlet理解

部分转载自&#xff1a;https://blog.csdn.net/javaloveiphone/article/details/8154791 从上图可以看出 Tomcat 的容器分为四个等级&#xff0c;真正管理Servlet 的容器是Context 容器&#xff0c;一个 Context 对应一个 Web 工程。除了将 Servlet 包装成 StandardWrapper 并作…

java serverlet_Serverlet程序

Serverlet是用Java编写的服务器端程序;主要用于交互地浏览和修改数据&#xff0c;生成动态Web内容; 一个serverlet就是一个继承于HttpServlet抽象类的Java类&#xff1b;下面先看一个简单的例子 import javax.servlet.*;importjavax.servlet.http.HttpServlet;importjavax.serv…

serverlet 区别_jsp serverlet 区别

JSP和Servlet的概念对于JSP初学者来说比较不清楚&#xff0c;以下总结一些个人看法&#xff1a; (1).简单的来说Jsp就是含有Java代码的html&#xff0c;而servlet是含有html的Java代码&#xff1b; (2).Jsp最终也是被解释为servlet并编译再执行&#xff0c;Jsp不过是servlet的另…

Java开发之ServLet详解

一、什么是ServLet&#xff1f; serverLet是javaEE中运行于服务器端的&#xff0c;用于接收和响应HTTP协议的请求的程序。 二、ServLet的三种实现方式 1、实现ServLet接口 步骤&#xff1a; &#xff08;1&#xff09;实现ServLet接口 &#xff08;2&#xff09;重写包括s…

Serverlet的生命周期

1.Servlet的生命周期 Servlet没有main()方法&#xff0c;不能独立运行&#xff0c;它的运行完全由Servlet引擎来控制和调度。所谓生命周期 &#xff0c;指的是servlet容器何时创建servlet实例、何时调用其方法进行请求的处理、何时并销毁其实例的 整个过程。其完整的周期包括…

VRRP协议以及关联Track详解

一、实验 详细解释可以直接查看下面连接&#xff0c;是我转发CSDN大佬的连接&#xff0c;直接上实验 VRRP详解 R1&#xff0c;R2充当两个网段的PC、分别是13.1.1.0 和24.2.2.0 R5&#xff0c;R6充当两个PC的接入层交换机 R5 eth0/1属于vlan 2000&#xff0c;R6 eth0/2属于vlan…