Kruskal算法

合集下载

Kruskal算法和Prim算法

Kruskal算法和Prim算法

Kruskal算法和Prim算法本节所阐述的两种最小生成树算法是上节所介绍的一般算法的细化。

每个算法均采用一特定规则来确定GENERIC-MST算法第3行所描述的安全边;在Kruskal算法中,集合A是一森林,加大集合A中的安全边总是图中连结两不同连通支的最小权边。

在Prim算法中,集合A仅形成单棵树。

添加入集合A的安全边总是连结树与一非树结点的最小权边。

Kruskal算法Kruskal算法是直接基于上一节中给出的一般最小生成树算法的基础之上的。

该算法找出森林中连结任意两棵树的所有边中具有最小权值的边(u,v)作为安全边,并把它添加到正在生长的森林中。

设C1和C2表示边(u,v)连结的两棵树。

因为(u,v)必是连C1和其他某棵树的一条轻边,所以由推论2可知(u,v)对C1是安全边。

Kruskal算法同时也是一种贪心算法,因为算法每一步添加到森林中的边的权值都尽可能小。

Kruskal算法的实现类似于计算连通支的算法。

它使用了分离集合数据结构以保持数个互相分离的元素集合。

每一集合包含当前森林中某个树的结点,操作FIND-SET(u)返回包含u的集合的一个代表元素,因此我们可以通过FIND-SET(v)来确定两结点u和v是否属于同一棵树,通过操作UNION来完成树与树的联结。

MST-KRUSKAL(G,w)1. A←∅2. for 每个结点v V[G]3. do MAKE-SET(v)4. 根据权w的非递减顺序对E的边进行排序5. for 每条边(u,v)∈E,按权的非递减次序6. do if FIND-SET(u) ≠ FIND-SET(v)7. then A←A∪{(u,v)}8. UNION(u,v)9 return AKruskal算法的工作流程如图4所示。

阴影覆盖的边属于正在生成的森林A。

算法按权的大小顺序考察各边。

箭头指向算法每一步所考察到的边。

第1-3行初始化集合A为空集并建立|V|棵树,每裸树包含图的一个结点。

Kruskal算法

Kruskal算法

最小生成树的Kruskal算法Kruskal算法基本思想:每次选不属于同一连通分量(保证不生成圈)且边权值最小的顶点,将边加入MST,并将所在的2个连通分量合并,直到只剩一个连通分量排序使用Quicksort(O(eloge))检查是否在同一连通分量用Union-Find,每次Find和union运算近似常数Union-Find使用rank启发式合并和路径压缩总复杂度O(eloge)=O(elogv) (因为e<n(n-1)/2)}constmaxn=100;maxe=maxn*maxn;typeedge=recorda,b :integer; //边的2个顶点len :integer; //边的长度end;varedges :array[0..maxe]of edge; //保存所有边的信息p,r :array[0..maxn]of integer; //p保存i的父亲节点,r用来实现Union-Find的rank启发式n,e :integer; //n为顶点数,e为边数procedure swap(a,b:integer); //交换beginedges[0]:=edges[a];edges[a]:=edges[b];edges[b]:=edges[0];end;procedure quicksort(l,r:integer); //快速排序varx,i,j :integer;beginx:=edges[random(r-l+1)+l].len;i:=l;j:=r;repeatwhile edges[i].len<x do inc(i);while edges[j].len>x do dec(j);if i<=j thenbeginswap(i,j);inc(i);dec(j);enduntil i>j;if l<j then quicksort(l,j);if i<r then quicksort(i,r);end;procedure init;vari :integer;beginassign(input,'g.in');reset(input);readln(n,e);for i:=1 to e do readln(edges[i].a,edges[i].b,edges[i].len); //从文件读入图的信息for i:=1 to n do p[i]:=i; //初始化并查集randomize;quicksort(1,e); //使用快速排序将边按权值从小到大排列end;function find(x:integer):integer; //并查集的Find,用来判断2个顶点是否属于一个连通分量beginif x<>p[x] then p[x]:=find(p[x]);find:=p[x]end;procedure union(a,b:integer); //如果不属于且权值最小则将2个顶点合并到一个连通分量vart :integer;begina:=find(a);b:=find(b);if r[a]>r[b] then begin t:=a;a:=b;b:=t end;if r[a]=r[b]then inc(r[a]);p[a]:=b;end;procedure kruskal; //主过程varen :integer; //en为当前边的编号count :integer; //统计进行了几次合并。

库鲁斯卡尔(Kruskal)算法

库鲁斯卡尔(Kruskal)算法

贪心策略是指从问题的初始状态出发,通过若干次的贪心选择而得出最优值(或较优解)的一种解题方法。

Ⅰ、库鲁斯卡尔(Kruskal)算法【定义4】设图G=(V,E)是一简单连通图,|V| =n,|E|=m,每条边ei都给以权W ,W 假定是边e 的长度(其他的也可以),i=1,2,3,...,m。

求图G的总长度最短的树,这就是最短树问题。

kruskal算法的基本思想是:首先将赋权图G的边按权的升序排列,不失一般性为:e ,e ,......,e 。

其中W ≤W ,然后在不构成回路的条件下择优取进权最小的边。

其流程如下:(1)对属于E的边进行排序得e ≤e ≤...... ≤e 。

(2)初始化操作 w←0,T←ф,k←0,t←0;(3)若t=n-1,则转(6),否则转(4)(4)若T∪{e }构成一回路,则作【k←k+1,转(4)】(5) T←T∪{ e },w←w+ w ,t←t+1,k←k+1,转(3)(6)输出T,w,停止。

下面我们对这个算法的合理性进行证明。

设在最短树中,有边〈v ,v 〉,连接两顶点v ,v ,边〈v ,v 〉的权为wp,若〈v ,v 〉加入到树中不能保证树的总长度最短,那么一定有另一条边〈v ,v 〉或另两条边〈v ,v 〉、〈v ,v 〉,且w<vi,vj><wp或w<vi,vk>+w〈vk,vj〉<wp,因为〈v ,v 〉、〈v ,v 〉不在最短树中,可知当〈v ,v 〉、〈v ,v 〉加入到树中时已构成回路,此时程序终止。

因为〈v ,v 〉∈ T,〈v ,v 〉∈T且w〈vI,vk〉+w〈vk,vj〉<w p,与程序流程矛盾。

普林(Prim)算法:Kruskal算法采取在不构成回路的条件下,优先选择长度最短的边作为最短树的边,而Prim则是采取了另一种贪心策略。

已知图G=(V,E),V={v ,v ,v ,..., v },D=(d )是图G的矩阵,若〈v ,v 〉∈E,则令dij=∞,并假定dij=∞Prim算法的基本思想是:从某一顶点(设为v )开始,令S←{v },求V/S中点与S中点v 距离最短的点,即从矩阵D的第一行元素中找到最小的元素,设为d ,则令S ←S∪ { v },继续求V/S中点与S的距离最短的点,设为v ,则令S←S∪{ v },继续以上的步骤,直到n个顶点用n-1条边连接起来为止。

kruskal算法

kruskal算法

kruskal算法百科名片K r u s k a l算法每次选择n- 1条边,所使用的贪婪准则是:从剩下的边中选择一条不会产生环路的具有最小耗费的边加入已选择的边的集合中。

注意到所选取的边若产生环路则不可能形成一棵生成树。

K r u s k a l算法分e 步,其中e 是网络中边的数目。

按耗费递增的顺序来考虑这e 条边,每次考虑一条边。

当考虑某条边时,若将其加入到已选边的集合中会出现环路,则将其抛弃,否则,将它选入。

目录[隐藏]Kruskal算法普里姆算法(prim算法)Kruskal算法普里姆算法(prim算法)[编辑本段]Kruskal算法算法定义克鲁斯卡尔算法假设WN=(V,{E}) 是一个含有n 个顶点的连通网,则按照克鲁斯卡尔算法构造最小生成树的过程为:先构造一个只含n 个顶点,而边集为空的子图,若将该子图中各个顶点看成是各棵树上的根结点,则它是一个含有n 棵树的一个森林。

之后,从网的边集 E 中选取一条权值最小的边,若该条边的两个顶点分属不同的树,则将其加入子图,也就是说,将这两个顶点分别所在的两棵树合成一棵树;反之,若该条边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。

依次类推,直至森林中只有一棵树,也即子图中含有n-1条边为止。

举例描述初始时没有任何边被选择。

边( 1 , 6)是最先选入的边,它被加入到欲构建的生成树中,得到图1 3 - 1 2 c。

下一步选择边(3,4)并将其加入树中(如图1 3 - 1 2 d所示)。

然后考虑边( 2,7 ,将它加入树中并不会产生环路,于是便得到图1 3 - 1 2 e。

下一步考虑边(2,3)并将其加入树中(如图1 3 - 1 2 f所示)。

在其余还未考虑的边中,(7,4)具有最小耗费,因此先考虑它,将它加入正在创建的树中会产生环路,所以将其丢弃。

此后将边(5,4)加入树中,得到的树如图13-12g 所示。

下一步考虑边(7,5),由于会产生环路,将其丢弃。

2.kruskal算法求解最小生成树算法

2.kruskal算法求解最小生成树算法

Kruskal算法是一种用于求解最小生成树的算法,它的主要特点是按边的权值大小进行排序,并逐步添加边,直到构成一棵生成树为止。

在实际应用中,Kruskal算法通常被用来解决各种最小生成树的问题,比如公路修建、通信网络的建设、电路板的设计等等。

本文将着重介绍Kruskal算法的原理、步骤和具体应用,以期为读者提供全面的了解和指导。

一、Kruskal算法的原理Kruskal算法是一种基于贪心策略的算法,它通过不断地选择边来构建生成树,直到所有的顶点都被包含在生成树中。

其基本原理可以概括如下:1. 将图中的所有边按权值大小进行排序。

2. 依次从小到大选择边,并检查是否形成环路。

3. 如果没有形成环路,则将该边添加到生成树中。

Kruskal算法的核心思想是“先小后大”,即先选择权值较小的边,直到所有的顶点都被包含在生成树中。

由于Kruskal算法是基于边来构建生成树的,因此它适用于稀疏图和稠密图,而且在实际应用中通常具有较好的效率。

二、Kruskal算法的步骤Kruskal算法的具体步骤可以简单总结为以下几个步骤:1. 初始化:将图中的所有边按权值大小进行排序。

2. 创建一个空的数组T来存储最小生成树的边。

3. 依次从排序后的边集合中选择边e,并检查是否添加e会形成环路。

4. 如果不形成环路,则将边e添加到数组T中。

5. 直到T中包含了n-1条边为止,其中n为顶点的个数。

三、Kruskal算法的具体实现下面我们通过一个简单的示例来说明Kruskal算法的具体实现步骤。

示例:假设有如下的图G和边集合E:顶点集合V:{A, B, C, D, E, F, G, H}边集合E:{(A, B, 4), (A, H, 8), (B, C, 8), (B, H, 11), (C, D, 7), (C, F, 4), (C, I, 2), (D, E, 9), (D, F, 14), (E, F, 10), (F, G, 2), (G, H, 1), (G, I, 6), (H, I, 7)}我们可以按照如下的步骤来求解最小生成树:1. 首先对边集合E进行按权值的排序:(E, F, 2), (G, H, 1), (C, I, 2), (A, B, 4), (C, F, 4), (H, I, 7), (C, D, 7), (D, E, 9), (A, H, 8), (B, C, 8), (G, I, 6), (B, H, 11), (D, F, 14)2. 初始化一个空的数组T来存储最小生成树的边,初始化一个数组parent来记录每个顶点的父节点。

Kruskal算法

Kruskal算法

1. Kruskal算法(1) 算法思想K r u s k a l算法每次选择n- 1条边,所使用的贪婪准则是:从剩下的边中选择一条不会产生环路的具有最小耗费的边加入已选择的边的集合中。

注意到所选取的边若产生环路则不可能形成一棵生成树。

K r u s k a l算法分e 步,其中e 是网络中边的数目。

按耗费递增的顺序来考虑这e 条边,每次考虑一条边。

当考虑某条边时,若将其加入到已选边的集合中会出现环路,则将其抛弃,否则,将它选入。

初始时没有任何边被选择。

边( 1 , 6)是最先选入的边,它被加入到欲构建的生成树中,得到图1 3 - 1 2 c。

下一步选择边( 3,4)并将其加入树中(如图1 3 - 1 2 d所示)。

然后考虑边( 2,7 ,将它加入树中并不会产生环路,于是便得到图1 3 - 1 2 e。

下一步考虑边( 2,3)并将其加入树中(如图1 3 - 1 2 f所示)。

在其余还未考虑的边中,(7,4)具有最小耗费,因此先考虑它,将它加入正在创建的树中会产生环路,所以将其丢弃。

此后将边( 5,4)加入树中,得到的树如图13-12g 所示。

下一步考虑边( 7,5),由于会产生环路,将其丢弃。

最后考虑边( 6,5)并将其加入树中,产生了一棵生成树,其耗费为9 9。

图1 - 1 3给出了K r u s k a l算法的伪代码。

(2)C代码/* Kruskal.cCopyright (c) 2002, 2006 by ctu_85All Rights Reserved.*//* I am sorry to say that the situation of unconnected graph is not concerned */#include "stdio.h"#define maxver 10#define maxright 100int G[maxver][maxver],record=0,touched[maxver][maxver];int circle=0;int FindCircle(int,int,int,int);int main(){int path[maxver][2],used[maxver][maxver];int i,j,k,t,min=maxright,exsit=0;int v1,v2,num,temp,status=0;restart:printf("Please enter the number of vertex(s) in the graph:\n"); scanf("%d",&num);if(num>maxver||num<0){printf("Error!Please reinput!\n");goto restart;}for(j=0;j<num;j++)for(k=0;k<num;k++){if(j==k){G[j][k]=maxright;used[j][k]=1;touched[j][k]=0;}elseif(j<k){re:printf("Please input the right between vertex %d and vertex %d,if no edge exists please input -1:\n",j+1,k+1);scanf("%d",&temp);if(temp>=maxright||temp<-1){printf("Invalid input!\n");goto re;}if(temp==-1)temp=maxright;G[j][k]=G[k][j]=temp;used[j][k]=used[k][j]=0;touched[j][k]=touched[k][j]=0;}}for(j=0;j<num;j++){path[j][0]=0;path[j][1]=0;}for(j=0;j<num;j++){status=0;for(k=0;k<num;k++)if(G[j][k]<maxright){status=1;break;}if(status==0)break;}for(i=0;i<num-1&&status;i++){for(j=0;j<num;j++)for(k=0;k<num;k++)if(G[j][k]<min&&!used[j][k]){v1=j;v2=k;min=G[j][k];}if(!used[v1][v2]){used[v1][v2]=1;used[v2][v1]=1;touched[v1][v2]=1;touched[v2][v1]=1;path[0]=v1;path[1]=v2;for(t=0;t<record;t++)FindCircle(path[t][0],path[t][0],num,path[t][0]);if(circle){/*if a circle exsits,roll back*/circle=0;i--;exsit=0;touched[v1][v2]=0;touched[v2][v1]=0;min=maxright;}else{record++;min=maxright;}}}if(!status)printf("We cannot deal with it because the graph is not connected!\n"); else{for(i=0;i<num-1;i++)printf("Path %d:vertex %d to vertex %d\n",i+1,path[0]+1,path[1]+1); }return 1;}int FindCircle(int start,int begin,int times,int pre){ /* to judge whether a circle is produced*/int i;for(i=0;i<times;i++)if(touched[begin]==1){if(i==start&&pre!=start){circle=1;return 1;break;}elseif(pre!=i)FindCircle(start,i,times,begin);elsecontinue;}return 1;}。

库鲁斯卡尔(Kruskal)算法

库鲁斯卡尔(Kruskal)算法

贪心策略是指从问题的初始状态出发,通过若干次的贪心选择而得出最优值(或较优解)的一种解题方法。

Ⅰ、库鲁斯卡尔(Kruskal)算法【定义4】设图G=(V,E)是一简单连通图,|V| =n,|E|=m,每条边ei都给以权W ,W 假定是边e 的长度(其他的也可以),i=1,2,3,...,m。

求图G的总长度最短的树,这就是最短树问题。

kruskal算法的基本思想是:首先将赋权图G的边按权的升序排列,不失一般性为:e ,e ,......,e 。

其中W ≤W ,然后在不构成回路的条件下择优取进权最小的边。

其流程如下:(1)对属于E的边进行排序得e ≤e ≤...... ≤e 。

(2)初始化操作 w←0,T←ф,k←0,t←0;(3)若t=n-1,则转(6),否则转(4)(4)若T∪{e }构成一回路,则作【k←k+1,转(4)】(5) T←T∪{ e },w←w+ w ,t←t+1,k←k+1,转(3)(6)输出T,w,停止。

下面我们对这个算法的合理性进行证明。

设在最短树中,有边〈v ,v 〉,连接两顶点v ,v ,边〈v ,v 〉的权为wp,若〈v ,v 〉加入到树中不能保证树的总长度最短,那么一定有另一条边〈v ,v 〉或另两条边〈v ,v 〉、〈v ,v 〉,且w<vi,vj><wp或w<vi,vk>+w〈vk,vj〉<wp,因为〈v ,v 〉、〈v ,v 〉不在最短树中,可知当〈v ,v 〉、〈v ,v 〉加入到树中时已构成回路,此时程序终止。

因为〈v ,v 〉∈ T,〈v ,v 〉∈T且w〈vI,vk〉+w〈vk,vj〉<w p,与程序流程矛盾。

普林(Prim)算法:Kruskal算法采取在不构成回路的条件下,优先选择长度最短的边作为最短树的边,而Prim则是采取了另一种贪心策略。

已知图G=(V,E),V={v ,v ,v ,..., v },D=(d )是图G的矩阵,若〈v ,v 〉∈E,则令dij=∞,并假定dij=∞Prim算法的基本思想是:从某一顶点(设为v )开始,令S←{v },求V/S中点与S中点v 距离最短的点,即从矩阵D的第一行元素中找到最小的元素,设为d ,则令S ←S∪ { v },继续求V/S中点与S的距离最短的点,设为v ,则令S←S∪{ v },继续以上的步骤,直到n个顶点用n-1条边连接起来为止。

kruskal算法回环判断方法

kruskal算法回环判断方法

kruskal算法回环判断方法(原创实用版4篇)《kruskal算法回环判断方法》篇1Kruskal 算法是一种用于寻找最小生成树的算法。

在Kruskal 算法中,边按照权重从小到大排序,然后依次将边加入到图中,但要避免形成环。

为了判断是否形成环,Kruskal 算法使用了一种称为“回环判断方法”的技术。

具体来说,在加入一条边之前,需要检查这条边是否与已加入的边形成环。

如果形成环,则这条边不能加入到图中。

回环判断方法的实现可以通过使用并查集数据结构来实现。

具体来说,对于每一条边,都使用一个并查集来记录这条边所连接的顶点属于哪个连通分量。

在加入一条边之前,需要检查这条边的两个端点是否属于同一个连通分量。

如果属于同一个连通分量,则说明加入这条边会形成环,不能加入。

《kruskal算法回环判断方法》篇2Kruskal 算法是一种用于寻找最小生成树的算法。

在寻找最小生成树时,需要判断一个树是否是一个回环。

回环是指一个节点通过一条边连接到自己,形成一个环。

Kruskal 算法使用并查集数据结构来维护边集,并使用disjoint sets data structure 来判断是否存在回环。

在disjoint sets data structure 中,每个节点代表一个连通分量(也可以理解为森林中的一个组成部分),每个节点的父节点是指向它的连通分量的根节点。

当加入一条新边时,需要将这条边的两个端点的节点合并到同一个连通分量中。

如果这条边的两个端点已经在同一个连通分量中,那么就说明存在回环。

具体实现时,可以使用一个数组来记录每个节点的父节点,当加入一条新边时,需要遍历这条边的两个端点的父节点,如果它们相同,就说明存在回环。

以下是一个示例代码:``` pythonclass DisjointSet:def __init__(self):self.size = 0self.parent = [None] * (100000 + 1)def find(self, x):if self.parent[x] is None:return xelse:return self.find(self.parent[x])def union(self, x, y):x_root = self.find(x)y_root = self.find(y)if x_root == y_root:#存在回环returnelse:if self.size[x_root] < self.size[y_root]:self.size[x_root] += self.size[y_root]self.parent[x_root] = x_rootelse:self.size[y_root] += self.size[x_root]self.parent[y_root] = x_root```在以上代码中,`self.size[i]` 表示连通分量i 的大小,`self.parent[i]` 表示连通分量i 的根节点。

kruskal算法的题

kruskal算法的题

Kruskal 算法及其应用Kruskal 算法是一种求解最小生成树的算法,其思想是将边按照权值从小到大排序,然后依次将边加入到已构建的生成树中,直到生成树中的边数等于顶点数减一。

Kruskal 算法具有良好的时间复杂度和空间复杂度,因此在实际应用中得到广泛的应用。

本文将介绍 Kruskal 算法的基本思想、证明方法以及其在实际应用中的应用。

下面是本店铺为大家精心编写的4篇《Kruskal 算法及其应用》,供大家借鉴与参考,希望对大家有所帮助。

《Kruskal 算法及其应用》篇1一、Kruskal 算法的基本思想Kruskal 算法是一种求解最小生成树的算法,其基本思想是将边按照权值从小到大排序,然后依次将边加入到已构建的生成树中,直到生成树中的边数等于顶点数减一。

Kruskal 算法的时间复杂度为O(ElogE),其中 E 表示边的数量。

Kruskal 算法的实现过程可以分为三个步骤:1. 将所有边按照权值从小到大排序;2. 初始化一个空的生成树;3. 依次将排序后的边加入到生成树中,直到生成树中的边数等于顶点数减一。

二、Kruskal 算法的证明方法Kruskal 算法的正确性可以通过证明生成的生成树是最小生成树来证明。

具体来说,可以采用贪心算法的思路,证明 Kruskal 算法得到的生成树是局部最优的,即每次加入的边都是当前状态下的最小边。

证明过程可以分为以下几个步骤:1. 证明 Kruskal 算法得到的生成树是连通的;2. 证明 Kruskal 算法得到的生成树是树结构;3. 证明 Kruskal 算法得到的生成树是最小生成树。

三、Kruskal 算法在实际应用中的应用Kruskal 算法在实际应用中得到广泛的应用,如下:1. 最小生成树:Kruskal 算法可以用于求解最小生成树,将其应用于网络设计、图像处理、生物信息学等领域。

2. 单源最短路径:Kruskal 算法可以用于求解单源最短路径,将其应用于路由算法、图像处理、生物信息学等领域。

kruskal算法c++程序

kruskal算法c++程序

Kruskal算法是一种用于求解最小生成树的贪心算法,它能够有效地找到一个加权连通图中的最小生成树。

在本文中,我们将通过C++程序来实现Kruskal算法,并对其原理进行详细的讲解和分析。

一、Kruskal算法原理1. Kruskal算法的基本思想Kruskal算法的基本思想是:将图中的所有边按照权值的大小进行递增排序,然后依次选取权值最小的边,若加入该边不会形成环,则将其加入最小生成树中,直到最小生成树中含有V-1条边为止。

2. Kruskal算法的步骤Kruskal算法的具体步骤如下:(1)将图中的所有边按照权值的大小进行递增排序(2)依次选取权值最小的边(3)若加入该边不会形成环,则将其加入最小生成树中(4)直到最小生成树中含有V-1条边为止3. Kruskal算法的实现要点(1)利用并查集来判断加入边是否会形成环(2)采用排序算法对边进行排序(3)采用循环遍历所有边,并判断是否加入最小生成树二、Kruskal算法C++程序实现```C++#include <iostream>#include <vector>#include <algorithm>using namespace std;// 定义边的结构体struct Edge {int from, to, weight;Edge(int f, int t, int w) : from(f), to(t), weight(w) {} };// 定义并查集class UnionFind {public:vector<int> parent;UnionFind(int n) : parent(n) {for (int i = 0; i < n; i++) {parent[i] = i;}}int find(int x) {return x == parent[x] ? x : (parent[x] = find(parent[x]));}void unite(int x, int y) {parent[find(x)] = find(y);}bool same(int x, int y) {return find(x) == find(y);}};// 定义Kruskal算法vector<Edge> kruskal(int n, vector<Edge> edges) {sort(edges.begin(), edges.end(), [](const Edge a, const Edge b) {return a.weight < b.weight;});UnionFind uf(n);vector<Edge> res;for (const Edge e : edges) {if (!uf.same(e.from, e.to)) {uf.unite(e.from, e.to);res.push_back(e);}}return res;}int main() {int n = 6;vector<Edge> edges = {Edge(0, 1, 4), Edge(0, 2, 4), Edge(1, 2, 2), Edge(1, 3, 3), Edge(1, 4, 1), Edge(2, 3, 4), Edge(3, 4, 2), Edge(3, 5, 5), Edge(4, 5, 3)};vector<Edge> minSpanningTree = kruskal(n, edges);for (const Edge e : minSpanningTree) {cout << e.from << " - " << e.to << " : " << e.weight << endl;}return 0;}```三、Kruskal算法C++程序分析1. 我们定义了一个边的结构体来表示图中的边,并且定义了并查集来判断加入边是否会形成环。

Kruskal算法

Kruskal算法

1. 概览Kruskal算法是一种用来寻找最小生成树的算法,由Joseph Kruskal在1956年发表。

用来解决同样问题的还有Prime 算法和Boruvka 算法等。

三种算法都是贪婪算法的应用。

和Boruvka 算法不同的地方是,Kruskal 算法在图中存在相同权值的边时也有效。

2. 算法简单描述1.记Graph 中有v个顶点,e个边2.新建图Graph new,Graph new中拥有原图中相同的e个顶点,但没有边3.将原图Graph new中所有e个边按权值从小到大排序4.循环:从权值最小的边开始遍历每条边直至图Graph new中所有的节点都在同一个连通分量中如果这条边连接的两个节点于图Graph new中不在同一个连通分量中添加这条边到图Graph new中图例描述:3. 简单证明Kruskal算法对图的顶点数n 做归纳,证明Kruskal 算法对任意n 阶图适用。

归纳基础:n = 1,显然能够找到最小生成树。

归纳过程:假设Kruskal 算法对n ≤k 阶图适用,那么,在k + 1 阶图G 中,我们把最短边的两个端点a 和b 做一个合并操作,即把u 与v 合为一个点v',把原来接在u 和v 的边都接到v' 上去,这样就能够得到一个k阶图G'(u ,v 的合并是k + 1 少一条边),G' 最小生成树T' 可以用Kruskal 算法得到。

我们证明T' + {<u,v>} 是G 的最小生成树。

用反证法,如果T' + {<u,v>} 不是最小生成树,最小生成树是T,即W(T) < W(T' + {<u,v>})。

显然T 应该包含<u,v>,否则,可以用<u,v> 加入到T 中,形成一个环,删除环上原有的任意一条边,形成一棵更小权值的生成树。

而T - {<u,v>},是G' 的生成树。

Prim算法和Kruskal算法

Prim算法和Kruskal算法

Prim算法和Kruskal算法Prim算法和Kruskal算法都能从连通图找出最小生成树。

区别在于Prim算法是挨个找,而Kruskal是先排序再找。

一、Prim算法:Prim算法实现的是找出一个有权重连通图中的最小生成树,即:具有最小权重且连接到所有结点的树。

(强调的是树,树是没有回路的)。

Prim算法是这样来做的:首先以一个结点作为最小生成树的初始结点,然后以迭代的方式找出与最小生成树中各结点权重最小边,并加入到最小生成树中。

加入之后如果产生回路则跳过这条边,选择下一个结点。

当所有结点都加入到最小生成树中之后,就找出了连通图中的最小生成树了。

Prim算法最小生成树查找过程:注意:若候选轻边集中的轻边不止一条,可任选其中的一条扩充到T中。

连通网的最小生成树不一定是惟一的,但它们的权相等。

【例】在上图(e)中,若选取的轻边是(2,4)而不是(2,1)时,则得到如图(h)所示的另一棵MST。

算法特点该算法的特点是当前形成的集合T始终是一棵树。

将T中U和TE分别看作红点和红边集,V-U看作蓝点集。

算法的每一步均是在连接红、蓝点集的紫边中选择一条轻边扩充进T中。

MST性质保证了此边是安全的。

T从任意的根r开始,并逐渐生长直至U=V,即T 包含了C中所有的顶点为止。

MST性质确保此时的T是G的一棵MST。

因为每次添加的边是使树中的权尽可能小,因此这是一种"贪心"的策略。

算法分析该算法的时间复杂度为O(n2)。

与图中边数无关,该算法适合于稠密图。

算法演示:/sjjg/DataStructure/DS/web/flashhtml/prim.htm二、Kruskal算法:Kruskal算法与Prim算法的不同之处在于,Kruskal在找最小生成树结点之前,需要对所有权重边做从小到大排序。

将排序好的权重边依次加入到最小生成树中,如果加入时产生回路就跳过这条边,加入下一条边。

当所有结点都加入到最小生成树中之后,就找出了最小生成树。

最短路径问题(Dijkstra算法)和最小生成树(Kruskal算法和Prim算法)

最短路径问题(Dijkstra算法)和最小生成树(Kruskal算法和Prim算法)
ift(j)==tmax
t(j)=tmin;
end
end
end
ifk==n
break;
end
end
T;
c;
Prim算法程序:
function[T c] =Primf(a)
%a表示权值矩阵
%c表示生成树的权和
%T表示生成树的边集合
l=length(a);
a(a==0)=inf;
k=1:l;
listV(k)=0;
上机实验1、2
1.最短路径问题(Dijkstra算法)
2.最小生成树(Kruskal算法和Prim算法)
一、最短路径问题(Dijkstra算法)
实验问题描述:如图的交通网络,每条弧上的数字代表车辆在该路段行驶所需的时间,有向边表示单行道,无向边表示可双向行驶。若有一批货物要从1号顶点运往11号顶点,问运货车应沿哪条线路行驶,才能最快地到达目的地。
listV(1)=1;
e=1;
while(e<l)
min=inf;
fori=1:l
iflistV(i)==1
forj=1:l
iflistV(j)==0&min>a(i,j)
min=a(i,j);b=a(i,j);
s=i;d=j;
end
end
end
end
listV(d)=1;
distance(e)=b;
T =
3 4 1 2
4 5 3 5
c =
10
>> a=[0 5 3 7 inf;5 0 8 inf 4;3 8 0 1 6;7 inf 1 0 2;inf 4 6 2 0];
>> [T c] =Primf(a)

克鲁斯卡尔算法(Kruskal算法)(最小生成树算法)-贪心

克鲁斯卡尔算法(Kruskal算法)(最小生成树算法)-贪心

克鲁斯卡尔算法(Kruskal算法)(最⼩⽣成树算法)-贪⼼克鲁斯卡尔算法:Kruskal算法是⼀种⽤来查找的算法,由Joseph Kruskal在1956年发表。

⽤来解决同样问题的还有和Boruvka算法等。

三种算法都是的应⽤。

和Boruvka算法不同的地⽅是,Kruskal算法在图中存在相同权值的边时也有效。

基本思想:先构造⼀个只含 n 个顶点、⽽边集为空的⼦图,把⼦图中各个顶点看成各棵树上的根结点,之后,从⽹的边集 E 中选取⼀条权值最⼩的边,若该条边的两个顶点分属不同的树,则将其加⼊⼦图,即把两棵树合成⼀棵树,反之,若该条边的两个顶点已落在同⼀棵树上,则不可取,⽽应该取下⼀条权值最⼩的边再试之。

依次类推,直到森林中只有⼀棵树,也即⼦图中含有 n-1 条边为⽌。

发现⼀个好的视频:下图为初始图、只含有点的森林和点与点之间的联系循环找权值最⼩的边依次向下循环...输⼊:6 101 2 61 3 11 4 52 3 52 5 33 4 53 5 63 6 44 6 25 6 6输出:V1-V3=1V4-V6=2V2-V5=3V3-V6=4V5-V6=515代码:#include <iostream>#include <bits/stdc++.h>using namespace std;#define MAX 100int Find(int parent[],int i){while(parent[i]>0){i=parent[i];}return i;}void Kruskal(int u[],int v[],int w[],int n,int m){int parent[MAX];int sum=0;for(int i=1;i<=n;i++) //初始化{parent[i]=0;}int a,b;for(int i=1;i<=m;i++){a=Find(parent,u[i]);b=Find(parent,v[i]);if(a!=b) //a==b说明成环{parent[a]=b;cout<<"V"<<a<<"-"<<"V"<<b<<"="<<w[i]<<endl; sum+=w[i];}}cout<<sum;}int main(){int n,m;int u[MAX],v[MAX],w[MAX];cin>>n>>m;for(int i=1;i<=m;i++){cin>>u[i]>>v[i]>>w[i];}for(int i=1;i<=m;i++) //排序{int min=i;for(int j=i+1;j<=m;j++){if(w[min]>w[j]){min=j;}}swap(u[i],u[min]);swap(v[i],v[min]);swap(w[i],w[min]);}Kruskal(u,v,w,n,m);return0;}。

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

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

数据结构与算法——克鲁斯卡尔(Kruskal)算法⽬录应⽤场景-公交站问题某城市新增 7 个站点(A, B, C, D, E, F, G) ,现在需要修路把 7 个站点连通,各个站点的距离⽤边线表⽰(权) ,⽐如 A – B 距离 12公⾥问:如何修路保证各个站点都能连通,并且总的修建公路总⾥程最短?如上图所⽰:要求和前⾯的普利姆算法中的修路问题是⼀样的要求,只是换了⼀个背景。

克鲁斯卡尔算法介绍克鲁斯卡尔(Kruskal)算法,是⽤来求加权连通图的最⼩⽣成树的算法。

基本思想:按照权值从⼩到⼤的顺序选择n-1条边,并保证这n-1条边不构成回路具体做法:⾸先构造⼀个只含 n 个顶点的森林然后依权值从⼩到⼤从连通⽹中选择边加⼊到森林中,并使森林中不产⽣回路,直⾄森林变成⼀棵树为⽌克鲁斯卡尔算法图解在含有 n 个顶点的连通图中选择 n-1 条边,构成⼀棵极⼩连通⼦图,并使该连通⼦图中 n-1 条边上权值之和达到最⼩,则称其为连通⽹的最⼩⽣成树。

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

有多种不同的连通⽅式,但是哪⼀种权值才是最优的呢?下⾯是克鲁斯卡尔算法的图解步骤:以上图 G4 为例,来对克鲁斯卡尔进⾏演⽰(假设,⽤数组 R 保存最⼩⽣成树结果)。

第 1 步:将边E,F [2]加⼊ R 中。

边E,F的权值最⼩,因此将它加⼊到最⼩⽣成树结果 R 中。

第 2 步:将边C,D [3]加⼊ R 中。

上⼀步操作之后,边C,D的权值最⼩,因此将它加⼊到最⼩⽣成树结果 R 中。

第 3 步:将边D,E [4]加⼊ R 中。

同理,权值最⼩第 4 步:将边B,F [7]加⼊ R 中。

上⼀步操作之后,边C,E [5]的权值最⼩,但C,E会和已有的边构成回路;因此,跳过边C,E。

同理,跳过边C,F [6]。

将边B,F加⼊到最⼩⽣成树结果R中。

第 5 步:将边E,G [8]加⼊ R 中。

同理第 6 步:将边A,B [12]加⼊ R 中。

prim算法和kruskal算法例题

prim算法和kruskal算法例题

一、概述在图论中,prim算法和kruskal算法是两种常用的最小生成树算法。

它们分别以不同的方式来寻找给定图的最小生成树,是解决最小生成树问题的有效方法。

本文将重点介绍prim算法和kruskal算法,并通过例题分析,展示它们的应用及原理。

二、prim算法1. prim算法概述2. prim算法步骤3. 例题分析:通过一个具体图示例,展示prim算法的应用过程,详细阐述每一步的操作及思路。

4. prim算法优缺点三、kruskal算法1. kruskal算法概述2. kruskal算法步骤3. 例题分析:通过一个具体图示例,展示kruskal算法的应用过程,详细阐述每一步的操作及思路。

4. kruskal算法优缺点四、prim算法和kruskal算法的比较1. 时间复杂度2. 空间复杂度3. 适用范围4. 其他特点五、例题分析总结通过对两种算法在具体例题中的应用过程分析,总结prim算法和kruskal算法的异同点,以及在实际问题中应用时的考虑因素。

六、结论根据对prim算法和kruskal算法的介绍及例题分析,总结两种算法的特点和应用场景,为不同情况下的最小生成树问题提供参考指导。

七、参考文献列出本文所参考的相关书籍、文献或全球信息站信息,为读者进一步了解prim算法和kruskal算法提供便利。

八、附录可放置示例代码、补充说明或其他相关内容,以便读者更好地理解prim算法和kruskal算法。

由于当前训练模型对于编程题的掌握有一定限制,可以提供在Prim算法和Kruskal算法方面相关的例题解析和应用案例。

以下是一个基于图的例题及其解析。

假设有一个带权重的无向连通图G,图中的顶点集合为V,边的集合为E,每条边的权重由权重函数w(u, v)给出,其中u, v为边的两个顶点。

现在需要使用Prim算法和Kruskal算法来寻找图G的最小生成树。

首先我们需要给出一个具体的图G,如下所示:顶点集合V = {A, B, C, D, E}边的集合E = {(A, B, 3), (A, C, 1), (A, D, 5), (B, C, 4), (B, D, 6), (B, E, 2), (C, D, 7), (C, E, 8), (D, E, 9)}其中,每个元组表示一条边的起始顶点、终止顶点和权重。

数据结构(三十三)最小生成树(Prim、Kruskal)

数据结构(三十三)最小生成树(Prim、Kruskal)

数据结构(三⼗三)最⼩⽣成树(Prim、Kruskal) ⼀、最⼩⽣成树的定义 ⼀个连通图的⽣成树是⼀个极⼩的连通⼦图,它含有图中全部的顶点,但只有⾜以构成⼀棵树的n-1条边。

在⼀个⽹的所有⽣成树中,权值总和最⼩的⽣成树称为最⼩代价⽣成树(Minimum Cost Spanning Tree),简称为最⼩⽣成树。

构造最⼩⽣成树的准则有以下3条:只能使⽤该图中的边构造最⼩⽣成树当且仅当使⽤n-1条边来连接图中的n个顶点不能使⽤产⽣回路的边 对⽐两个算法,Kruskal算法主要是针对边来展开,边数少时效率会⾮常⾼,所以对于稀疏图有很⼤的优势;⽽Prim算法对于稠密图,即边数⾮常多的情况会更好⼀些。

⼆、普⾥姆(Prim)算法 1.Prim算法描述 假设N={V,{E}}是连通⽹,TE是N上最⼩⽣成树中边的集合。

算法从U={u0,u0属于V},TE={}开始。

重复执⾏下⾯的操作:在所有u属于U,v 属于V-U的边(u,v)中找⼀条代价最⼩的边(u0,v0)并加⼊集合TE,同时v0加⼊U,直到U=V为⽌。

此时TE中必有n-1条边,则T=(V,{TE})为N的最⼩⽣成树。

2.Prim算法的C语⾔代码实现/* Prim算法⽣成最⼩⽣成树 */void MiniSpanTree_Prim(MGraph G){int min, i, j, k;int adjvex[MAXVEX]; /* 保存相关顶点下标 */int lowcost[MAXVEX]; /* 保存相关顶点间边的权值 */lowcost[0] = 0;/* 初始化第⼀个权值为0,即v0加⼊⽣成树 *//* lowcost的值为0,在这⾥就是此下标的顶点已经加⼊⽣成树 */adjvex[0] = 0; /* 初始化第⼀个顶点下标为0 */for(i = 1; i < G.numVertexes; i++) /* 循环除下标为0外的全部顶点 */{lowcost[i] = G.arc[0][i]; /* 将v0顶点与之有边的权值存⼊数组 */adjvex[i] = 0; /* 初始化都为v0的下标 */}for(i = 1; i < G.numVertexes; i++){min = INFINITY; /* 初始化最⼩权值为∞, *//* 通常设置为不可能的⼤数字如32767、65535等 */j = 1;k = 0;while(j < G.numVertexes) /* 循环全部顶点 */{if(lowcost[j]!=0 && lowcost[j] < min)/* 如果权值不为0且权值⼩于min */{min = lowcost[j]; /* 则让当前权值成为最⼩值 */k = j; /* 将当前最⼩值的下标存⼊k */}j++;}printf("(%d, %d)\n", adjvex[k], k);/* 打印当前顶点边中权值最⼩的边 */lowcost[k] = 0;/* 将当前顶点的权值设置为0,表⽰此顶点已经完成任务 */for(j = 1; j < G.numVertexes; j++) /* 循环所有顶点 */{if(lowcost[j]!=0 && G.arc[k][j] < lowcost[j]){/* 如果下标为k顶点各边权值⼩于此前这些顶点未被加⼊⽣成树权值 */lowcost[j] = G.arc[k][j];/* 将较⼩的权值存⼊lowcost相应位置 */adjvex[j] = k; /* 将下标为k的顶点存⼊adjvex */}}}}Prim算法 3.Prim算法的Java语⾔代码实现package bigjun.iplab.adjacencyMatrix;/*** 最⼩⽣成树之Prim算法*/public class MiniSpanTree_Prim {int lowCost; // 顶点对应的权值public CloseEdge(Object adjVex, int lowCost) {this.adjVex = adjVex;this.lowCost = lowCost;}}private static int getMinMum(CloseEdge[] closeEdges) {int min = Integer.MAX_VALUE; // 初始化最⼩权值为正⽆穷int v = -1; // 顶点数组下标for (int i = 0; i < closeEdges.length; i++) { // 遍历权值数组,找到最⼩的权值以及对应的顶点数组的下标if (closeEdges[i].lowCost != 0 && closeEdges[i].lowCost < min) {min = closeEdges[i].lowCost;v = i;}}return v;}// Prim算法构造图G的以u为起始点的最⼩⽣成树public static void Prim(AdjacencyMatrixGraphINF G, Object u) throws Exception{// 初始化⼀个⼆维最⼩⽣成树数组minSpanTree,由于最⼩⽣成树的边是n-1,所以数组第⼀个参数是G.getVexNum() - 1,第⼆个参数表⽰边的起点和终点符号,所以是2 Object[][] minSpanTree = new Object[G.getVexNum() - 1][2];int count = 0; // 最⼩⽣成树得到的边的序号// 初始化保存相关顶点和相关顶点间边的权值的数组对象CloseEdge[] closeEdges = new CloseEdge[G.getVexNum()];int k = G.locateVex(u);for (int j = 0; j < G.getVexNum(); j++) {if (j!=k) {closeEdges[j] = new CloseEdge(u, G.getArcs()[k][j]);// 将顶点u到其他各个顶点权值写⼊数组中}}closeEdges[k] = new CloseEdge(u, 0); // 加⼊u到⾃⾝的权值0for (int i = 1; i < G.getVexNum(); i++) { // 注意,这⾥从1开始,k = getMinMum(closeEdges); // 获取u到数组下标为k的顶点的权值最短minSpanTree[count][0] = closeEdges[k].adjVex; // 最⼩⽣成树第⼀个值为uminSpanTree[count][1] = G.getVexs()[k]; // 最⼩⽣成树第⼆个值为k对应的顶点count++;closeEdges[k].lowCost = 0; // 下标为k的顶点不参与最⼩权值的查找了for (int j = 0; j < G.getVexNum(); j++) {if (G.getArcs()[k][j] < closeEdges[j].lowCost) {closeEdges[j] = new CloseEdge(G.getVex(k), G.getArcs()[k][j]);}}}System.out.print("通过Prim算法得到的最⼩⽣成树序列为: {");for (Object[] Tree : minSpanTree) {System.out.print("(" + Tree[0].toString() + "-" + Tree[1].toString() + ")");}System.out.println("}");}} 4.举例说明Prim算法实现过程 以下图为例: 测试类:// ⼿动创建⼀个⽤于测试最⼩⽣成树算法的⽆向⽹public static AdjacencyMatrixGraphINF createUDNByYourHand_ForMiniSpanTree() {Object vexs_UDN[] = {"V0", "V1", "V2", "V3", "V4", "V5", "V6", "V7", "V8"};int arcsNum_UDN = 15;int[][] arcs_UDN = new int[vexs_UDN.length][vexs_UDN.length];for (int i = 0; i < vexs_UDN.length; i++) // 构造⽆向图邻接矩阵for (int j = 0; j < vexs_UDN.length; j++)if (i==j) {arcs_UDN[i][j]=0;} else {arcs_UDN[i][j] = arcs_UDN[i][j] = INFINITY;}arcs_UDN[0][5] = 11;arcs_UDN[1][2] = 18;arcs_UDN[1][6] = 16;arcs_UDN[1][8] = 12;arcs_UDN[2][3] = 22;arcs_UDN[2][8] = 8;arcs_UDN[3][4] = 20;arcs_UDN[3][6] = 24;arcs_UDN[3][7] = 16;arcs_UDN[3][8] = 21;arcs_UDN[4][5] = 26;arcs_UDN[4][7] = 7;arcs_UDN[5][6] = 17;arcs_UDN[6][7] = 19;for (int i = 0; i < vexs_UDN.length; i++) // 构造⽆向图邻接矩阵for (int j = i; j < vexs_UDN.length; j++)arcs_UDN[j][i] = arcs_UDN[i][j];return new AdjMatGraph(GraphKind.UDN, vexs_UDN.length, arcsNum_UDN, vexs_UDN, arcs_UDN);}public static void main(String[] args) throws Exception {AdjMatGraph UDN_Graph = (AdjMatGraph) createUDNByYourHand_ForMiniSpanTree();MiniSpanTree_Prim.Prim(UDN_Graph, "V0");} 输出为:通过Prim算法得到的最⼩⽣成树序列为: {(V0-V1)(V0-V5)(V1-V8)(V8-V2)(V1-V6)(V6-V7)(V7-V4)(V7-V3)} 分析算法执⾏过程:从V0开始:-count为0,k为0,closeEdges数组的-lowCost为{0 10 INF INF INF 11 INF INF INF},adjVex数组为{V0,V0,V0,V0,V0,V0,V0,V0,V0}-⽐较lowCost,于是k为1,adjVex[1]为V0,minSpanTree[0]为(V0,V1),lowCost为{0 0 INF INF INF 11 INF INF INF}-k为1,与V1的权值⾏⽐较,得到新的-lowCost为:{0 0 18 INF INF 11 16 INF 12},adjVex数组为{V0,V0,V1,V0,V0,V0,V1,V0,V1}-⽐较lowCost,于是k为5,adjVex[5]为V0,minSpanTree[1]为(V0,V5),lowCost为{0 0 18 INF INF 0 16 INF 12}-k为5,与V5的权值⾏⽐较,得到新的-lowCost为{0 0 18 INF 26 0 16 INF 12},adjVex数组为{V0,V0,V1,V0,V5,V0,V1,V0,V1}-⽐较lowCost,于是k为8,adjVex[8]为V1,minSpanTree[2]为(V1,V8),lowCost为{0 0 18 INF INF 0 16 INF 0}... 三、克鲁斯卡尔(Kruskal)算法 1.Kruskal算法描述 Kruskal算法是根据边的权值递增的⽅式,依次找出权值最⼩的边建⽴的最⼩⽣成树,并且规定每次新增的边,不能造成⽣成树有回路,直到找到n-1条边为⽌。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Kruskal 算法构造最小生成树
构造赋权图(,,)G V E W =,其中12{,,,}n V v v v = 为顶点集合,其中i v 表示第i 个顶点,12{,,,,}i E e e e = 为边的集合,()ij n n W w ⨯=为邻接矩阵,其中
i j i j ij i j v v v v w v v ∈⎧⎪=⎨∞⎪⎩顶点与之间的距离,当(,)
E ,与之间没有边时
科茹斯克尔(Kruskal )算法如下: (1)选1e E ∈(E 为边的集合),使得1e 是权重最小的边。

(2)若12,,e i e e …,已选好,则从12{,,e }i E e e -…,中选取1i e +,使得 i )121{,,e }i e e +…,中无圈,且 ii )是1i e +是12{,,e }i E e e -…,中权重最小的边。

(3)直到选得1V e - 为止。

(V 是集合V 中元素的个数)
例:已知9个村庄之间的两两距离见表5,要架设通讯线路把9个村庄连接起来,求所需要通讯线的最小长度。

表5 10个村庄的两两距离数据(单位:km )
(,,)G V E W =,其中129{,,
,}V v v v = 为顶点集合,其中i v 表示第i 个村庄,12{,,,,}i E e e e = 为边的集合,99()ij W w ⨯=为邻接矩阵,其中
i j i j ij i j v v v v w v v ∈⎧⎪=⎨∞⎪⎩村庄与之间的距离,当(,)
E ,与之间没有通讯路线时
科茹斯克尔(Kruskal )算法如下: (1)选1e E ∈(E 为边的集合),使得1e 是距离最小的边。

(2)若12,,e i e e …,已选好,则从12{,,e }i E e e -…,中选取1i e +,使得 i )121{,,e }i e e +…,中无圈,且 ii )是1i e +是12{,,e }i E e e -…,中距离最小的边。

(3)直到选得8e 为止。

连通图程序见prim 算法。

clc, clear a=zeros(9);
a=xlsread('data.xls','B2:J10'); a(isnan(a))=0;
a=a'; %转成Matlab 需要的下三角元素 a=sparse(a); %转换为稀疏矩阵
b=graphminspantree(a,'Method','Kruskal') %注意要写Kruskal 算法,否则使用Prim 算法
L=sum(sum(b)) %求最小生成树的权重
view(biograph(b,[],'ShowArrows','off','ShowWeights','on')) %画最小生成树,%Matlab2014B 和2015A,'ShowWeights'有bug,属性值为'off'时没有问。

相关文档
最新文档