最小生成树的Kruskal算法实现

合集下载

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

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

Kruskal克鲁斯卡尔最⼩⽣成树算法(贪⼼算法)1. /*2. * Introduction to Algorithms3. * Chapter 23 --- MST.Kruskal4. * Tanky Woo @ 5. * 2012.1.76. */7.8. #include <</span>iostream>9. #include <</span>algorithm>10. using namespace std;11.12. const int maxint = 999999;13.14. typedef struct Road{15. int c1, c2;// a到b16. int value;//权值17. }Road;18.19. int no;20. int line;//记录实际关系数21. Road road[100];//设⼀个⽐较⼤的值,实际看输⼊最⼩⽣成树中:边数e=n-122. int node[101];//最⼩⽣成树:n顶点数23.24. bool myCmp(const Road &a,const Road &b)25. {26. if(a.value <</span> b.value)27. return 1;28. return 0;29. }30.31. //node[2]=1 node[8]=1 ,node[3]=1,共同的祖先,如果(3,8)加进去,则构成回路,不要32. //有点像并查集33. int Find_Set(int n)34. {35. if(node[n]==-1)36. return n;37. return node[n]= Find_Set(node[n]);38. }39.40. bool Merge(int s1,int s2)41. {42. int r1 = Find_Set(s1);43. int r2 = Find_Set(s2);44. if(r1 == r2)//如果相等证明构成回路,则直接返回⼀个0,不要把顶点加进来(下⼀步是加进去的)45. return 0;46. if(r1 <</span> r2)47. node[r2]= r1;48. else49. node[r1]= r2;50. return 1;51. }52.53. int main()54. {55. freopen("input.txt","r", stdin);56. //初始化全为-157. memset(node,-1, sizeof(node));58. scanf("%d",&no);59. scanf("%d",&line);60. int i;61. for(i=0; i<</span>line; ++i)62. {63. cin >> road[i].c1 >> road[i].c2 >> road[i].value;64. }65. sort(road, road+line, myCmp);66. int sum = 0, count = 0;// sum是MST的值,count是记录已使⽤的点数67. for(i=0; i<</span>line; ++i)68. {69. if(Merge(road[i].c1, road[i].c2))//如果返回的为0,则证明构成回路,不要加进70. {71. count ++;72. sum += road[i].value;73. }74. if(count == no-1)//e=n-1已经连通,可以退出75. break;76. }77. cout <</span><</span> sum <</span><</span> endl;78. return 0;79. }80.81.82. /*83. input.txt:84. 985. 1486. 1 2 487. 1 8 888. 2 3 889. 2 8 1190. 3 4 791. 3 6 492. 3 9 293. 4 5 994. 4 6 1495. 5 6 1096. 6 7 297. 7 8 198. 7 9 699. 8 9 7100. */。

编程实现最小生成树kruskal算法

编程实现最小生成树kruskal算法

编程实现最小生成树kruskal算法一、算法简介Kruskal算法是一种用于求解最小生成树的贪心算法。

它的基本思想是将所有边按照权值从小到大排序,然后依次选择权值最小的边,并将其加入到生成树中。

如果加入该边后不会形成环,则该边可以被加入到生成树中,否则舍弃该边,继续选择下一条权值最小的边。

二、算法流程1. 将所有边按照权值从小到大排序。

2. 初始化一个空的生成树。

3. 依次选择排序后的每条边,并判断是否会形成环。

4. 如果不会形成环,则将该边加入到生成树中。

5. 如果会形成环,则舍弃该边,继续选择下一条权值最小的边。

6. 直到所有节点都被遍历完毕或者已经找到了n-1条边。

三、代码实现Kruskal算法需要用到并查集来判断是否会形成环。

以下是Python代码实现:```pythonclass UnionFind:def __init__(self, n):self.parent = list(range(n))self.rank = [0] * ndef find(self, x):if self.parent[x] != x:self.parent[x] = self.find(self.parent[x]) return self.parent[x]def union(self, x, y):px, py = self.find(x), self.find(y)if px == py:return Falseif self.rank[px] > self.rank[py]:self.parent[py] = pxelif self.rank[px] < self.rank[py]:self.parent[px] = pyelse:self.parent[px] = pyself.rank[py] += 1return Truedef kruskal(n, edges):uf = UnionFind(n)edges.sort(key=lambda x: x[2])res, count = 0, 0for u, v, w in edges:if uf.union(u, v):res += wcount += 1if count == n - 1:breakreturn resn = 5 # 节点数目edges = [(0, 1, 2), (0, 2, 3), (1, 2, 1), (1, 3, 4), (2, 3, 5), (2, 4, 4), (3, 4 ,6)] # 边的列表,每个元素为(u,v,w),表示u和v之间有一条权值为w的边。

最小生成树克鲁斯卡尔算法详解

最小生成树克鲁斯卡尔算法详解

最小生成树克鲁斯卡尔算法详解转载自:数据结构中图结构的最小生成树克鲁斯卡尔算法详解我一直想把克鲁斯卡尔算法实现,但是由于马上就要考试了,而且自己由于天气寒冷等各种原因没能如愿。

不过在昨天一天的努力中,我终于完成了克鲁斯卡尔算法的实现。

算法是c++的,图的数据结构是以邻接矩阵为基础,并且使用了模板,所以可以对任何类型的顶点进行最小生成树的生成。

克鲁斯卡尔算法中的核心思想就是逐个在边的集合中找到最小的边,如果满足条件就将其构造,最后生成一个最小生成树。

它首先是一系列的顶点集合,并没有边,然后我们从邻接矩阵中寻找最小的边,看看它是否和现有的边连接成一个环,如果连接成环,则舍弃,另外取其它的边。

如果不连接成环,则接受这个边,并把其纳入集合中。

以此类推。

我们知道,一课有n个顶点的树(无论是树还是二叉树),它必定有n-1个边。

我们只需要对上述操作循环至少n-1次(因为可能选出的边会构成环,不是我们需要的边)。

下面就是我寻找最小边的c++代码:Code:min=INFINITY;for(i=0;i vexnum;i++){for(j=i;j vexnum;j++){if(arcs[i][j].adj!=INFINITY&&minarcs[i][j].adj){if(arcs[i][j].adj=vexSet.lowcost&&!vexSet.IsAlreadyIn(i,j)){min=arcs[i][j].adj;track_i=i;track_j=j;}}}}首先让min为最大(INFINITY),然后让其与邻接矩阵的一个个元素进行比较,我在遍历邻接矩阵的时候使用的是上三角(◥)法,因为无向网的邻接矩阵是对称矩阵。

当然我们必须记录满足调件的顶点的下标,所以track_i、track_j就变得必要了。

又因为我们要满足每次选取的最小权值的边呈递增数列,所以arcs[i][j].adj vexSet.lowcost(其中vexSet.lowcost为上次保存的最小边)就变得必要了。

c语言最小生成树kruskal算法

c语言最小生成树kruskal算法

c语言最小生成树kruskal算法Kruskal算法是一种用于解决最小生成树问题的贪心算法。

它的核心思想是通过不断添加边来构建最小生成树,直到所有的顶点都被连接在一起。

本文将介绍Kruskal算法的基本原理、实现步骤以及其在实际应用中的一些注意事项。

一、基本原理最小生成树是一个无向图的生成树中边的权值和最小的生成树。

Kruskal算法是一种基于边的贪心算法,它的主要思想是按照边的权值从小到大的顺序选择边,并且每次选择的边不能构成环,直到所有的顶点都被连接在一起。

二、实现步骤1. 将图的所有边按照权值从小到大排序;2. 依次选择权值最小的边,如果这条边的两个顶点不在同一棵生成树中,则将这条边添加到最小生成树中,并将这两个顶点合并为一棵生成树;3. 重复步骤2,直到所有的顶点都被连接在一起。

三、注意事项1. 在实现Kruskal算法时,需要使用并查集数据结构来判断两个顶点是否在同一棵生成树中。

并查集是一种用于处理不相交集合的数据结构,它支持合并和查询两个集合的操作,可以有效地判断两个顶点是否在同一棵生成树中。

2. 在选择边的过程中,需要注意避免选择会导致环形成的边,否则会破坏生成树的结构。

3. Kruskal算法可以应用于带权无向图,但是对于带权有向图,则需要使用其他算法来解决最小生成树的问题。

4. Kruskal算法的时间复杂度为O(ElogE),其中E为图的边数。

这是因为在算法的过程中需要对边进行排序,并且需要进行并查集的操作。

四、应用场景Kruskal算法在实际应用中有着广泛的应用场景,例如:1. 网络布线规划:在进行网络布线规划时,可以使用Kruskal算法来确定最优布线方案,以减少总线的长度和成本。

2. 铁路规划:在进行铁路线路规划时,可以使用Kruskal算法来确定最优的铁路线路,以减少运输成本和时间。

3. 电力传输:在进行电力传输规划时,可以使用Kruskal算法来确定最优的输电线路,以减少能量损耗和成本。

② kruskal最小生成树算法的定义和实现

② kruskal最小生成树算法的定义和实现

Krskal最小生成树算法是一种用来解决图论中最小生成树问题的算法。

它采用了一种贪心的策略,即每一步都选择权值最小的边,并且保证选择的边不会构成环,直到生成一棵最小生成树为止。

1. 算法的定义kruskal最小生成树算法的定义如下:输入:一个连通无向图G=(V,E),其中V是顶点集合,E是边的集合,每条边都有一个权值。

输出:G的最小生成树算法步骤:① 将图G的所有边按照权值从小到大进行排序。

② 初始化一个空的边集合T,该集合用来存放最小生成树的边。

③ 依次遍历排序后的边集合,对于每一条边e=(u,v),如果将该边添加到T中不会构成环,则将其添加到T中。

④ 重复步骤③,直到T中的边数等于V-1为止,此时T就是G的最小生成树。

2. 算法的实现下面是kruskal最小生成树算法的具体实现过程:```pythonclass UnionFind:def __init__(self, n):self.parent = [i for i in range(n)]def find(self, x):if self.parent[x] != x:self.parent[x] = self.find(self.parent[x]) return self.parent[x]def union(self, x, y):root_x = self.find(x)root_y = self.find(y)if root_x != root_y:self.parent[root_x] = root_ydef kruskal(graph):edges = []for u in range(len(graph)):for v in range(u+1, len(graph)):if graph[u][v] != 0:edges.append((u, v, graph[u][v])) edges.sort(key=lambda x: x[2])n = len(graph)result = []uf = UnionFind(n)for edge in edges:u, v, weight = edgeif uf.find(u) != uf.find(v):uf.union(u, v)result.append((u, v, weight))if len(result) == n - 1:breakreturn result```以上代码实现了kruskal最小生成树算法,其中使用了UnionFind类来实现并查集的功能,以判断是否构成环。

用Kruskal算法求无向图的最小生成树

用Kruskal算法求无向图的最小生成树

用Kruskal算法求无向图的最小生成树该图用邻接矩阵表示,邻接表原理与之相同。

可以指出的是,对于有向图,算法可以做得更加简单,因为对无向图的“回边”情况的处理比有向图回边情况的处理要复杂一些。

图1:输入示例图二:输入时若两点之间没有公共边,则将权值设置为-1。

程序设置处理的最大点数为10。

图三:注意到Kruskal算法的解答结果有时候不是唯一的,这个结果和对图遍历时的顺序有关,但是必需注意的是所有的最小生成树其网络代价和是一样的。

下面是源代码:/* 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[i][0]=v1;path[i][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[i][0]+1,path[i][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][i]==1){if(i==start&&pre!=start){circle=1;return 1;break;}elseif(pre!=i)FindCircle(start,i,times,begin); elsecontinue;}return 1;}。

基于VB的最小生成树KRUSKAL算法的实现

基于VB的最小生成树KRUSKAL算法的实现

每条边 的权值表示该条高速公路 的造价。要想使
总造价 最低 , 际 上 就 是 寻 找 该 网络 的 最 小 生 成 实 树 _ 。 目 前 , 解 最 小 生 成 树 的 经 典 算 法 有 1 j 求 K U K L算 法 ¨ ( 称 避 圈法 ) P I 算 法 j R SA 又 、 RM
关 键 词 : 权 连通 无 向 图 ;最 小生成树 ; B 加 V
中 图分 类 号 :P 9 T31
文 献标识 码 : A
文章 编号 :6 4— 4 5 2 1 ) 4—0 0 0 17 82 (00 0 1 1— 4
I pl m e a i n o RUSKAL’ g r t o m e nt to f K S Al o ihm f r
在 设计 任 意某 种 线 路 时 , 常 要 使 各 站 点 之 常 间保持 相通 , 然连 接 方法 很 多 , 需 要 找 出接 线 虽 但 总长度 最短 或使 某 种连 接 的总 费用 达 到 最 少 的连 接 方法 , 以尽 可 能 低 的 总造 价 建 设 若 干条 高 速 如 公路 , 把 个 城 市 联 系 在 一起 。n个 城 市 中 , 2 任
2 col f om t nS i c n eh o g , as g cபைடு நூலகம் rl nvr t, azo 3 0 0 C ia .S ho o r ai c neadT c nl F o e o G nuA r ut a U i sy L nh u7 07 , hn ) y i u ei
S l i i i um pa i e s d o VB o vng M n m S nn ng Tr e Ba e n
L in , A a— e ME a—un I a g Y N H ow n , I oya Q Y

最小生成树kruskal算法python代码解析

最小生成树kruskal算法python代码解析

最小生成树kruskal算法python代码解析Krulskal算法是一种常用于计算最小生成树的算法,主要用于求解无向带权图的最小生成树。

下面我们来了解一下Krulskal算法的具体实现方法。

算法设计思路Krulskal算法的实现主要通过以下几个步骤:1. 初始化:对于给定的图G,首先需要把图中所有的边按照权重大小从小到大排序,然后初始化一个空的边集合T。

2. 遍历:按照边的权重从小到大的顺序遍历所有的边。

3. 判定:对于当前遍历到的边,如果这条边的两个端点不在同一个连通块中,那么就将这条边加入到集合T中,同时将这两个端点所在的连通块合并成一个连通块。

4. 输出:最终输出的集合T即为图G的最小生成树。

代码解析下面给出Krulskal算法的Python代码实现。

1. 初始化```def init(graph):edges = []nodes = set()for start in graph:nodes.add(start)for end, weight in graph[start]:edges.append((start, end, weight))edges = sorted(edges, key=lambda e: e[2]) # 对边按照权重排序 return edges, nodes```在初始化中,我们将图G中所有的边按照权重大小从小到大排序,同时用一个set集合来存储所有的节点,方便后面的查找。

2. 遍历```def kruskal(graph):edges, nodes = init(graph)tree_edges = []disjoint_sets = [{node} for node in nodes]for start, end, weight in edges:start_set = find_set(disjoint_sets, start)end_set = find_set(disjoint_sets, end)if start_set != end_set:tree_edges.append((start, end))merge_sets(disjoint_sets, start_set, end_set)return tree_edges```在这一步中,我们按照边的权重从小到大的顺序遍历所有的边,同时查找每条边的两个端点所在的连通块。

Kruskal算法实现步骤

Kruskal算法实现步骤

Kruskal算法实现步骤Kruskal算法是一种用于解决最小生成树问题的贪心算法。

它的基本思想是通过不断选取权值最小的边来构建最小生成树。

下面将详细介绍Kruskal算法的实现步骤。

步骤一:初始化首先,我们需要将所有的边按照权值从小到大进行排序。

这可以使用快速排序等常用的排序算法来实现。

同时,我们也需要一个数组来记录每个顶点所在的连通分量。

步骤二:选择最小边从排序后的边中选择权值最小的一条边,并判断这条边所连接的两个顶点是否在不同的连通分量中。

如果是的话,则选择这条边加入最小生成树中;如果不是,则舍弃这条边继续选择下一条权值最小的边。

步骤三:更新连通分量将所选取的边连接的两个顶点加入同一个连通分量中。

这可以通过更新数组来实现,将其中一个顶点的连通分量值赋为另一个顶点的连通分量值。

步骤四:重复步骤二和步骤三依次选择下一条权值最小的边,并重复进行步骤二和步骤三,直到最小生成树的边数达到顶点数减一,或者遍历完所有的边。

步骤五:输出最小生成树最后,将构建好的最小生成树输出,即得到了问题的解。

通过上述的五个步骤,我们可以使用Kruskal算法来求解最小生成树问题。

该算法的时间复杂度主要取决于对边的排序操作,一般为O(ElogE),其中E为边的数量。

总结Kruskal算法是一种简单而有效的贪心算法,用于解决最小生成树问题。

它通过选择权值最小的边,并更新连通分量来逐步构建最小生成树。

该算法的核心是边的排序和判断两个顶点是否在同一连通分量中。

通过合理地使用该算法,我们可以在图论等领域中快速求解最小生成树的问题。

注意:本文仅为描述Kruskal算法实现步骤,未提供具体的代码实现。

如果您需要具体的代码,请参考相关的教材、论文或互联网资源。

数据结构-kruskal算法求最小生成树 实验报告

数据结构-kruskal算法求最小生成树 实验报告

一、问题简述题目:图的操作。

要求:用kruskal算法求最小生成树。

最短路径:①输入任意源点,求到其余顶点的最短路径。

②输入任意对顶点,求这两点之间的最短路径和所有路径。

二、程序设计思想首先要确定图的存储形式。

经过的题目要求的初步分析,发现该题的主要操作是路径的输出,因此采用边集数组(每个元素是一个结构体,包括起点、终点和权值)和邻接矩阵比较方便以后的编程。

其次是kruskal算法。

该算法的主要步骤是:GENERNIC-MIT(G,W)1. A←2. while A没有形成一棵生成树3 do 找出A的一条安全边(u,v);4.A←A∪{(u,v)};5.return A算法设置了集合A,该集合一直是某最小生成树的子集。

在每步决定是否把边(u,v)添加到集合A中,其添加条件是A∪{(u,v)}仍然是最小生成树的子集。

我们称这样的边为A 的安全边,因为可以安全地把它添加到A中而不会破坏上述条件。

然后就是Dijkstra算法。

Dijkstra算法基本思路是:假设每个点都有一对标号 (dj , pj),其中dj是从起源点s到点j的最短路径的长度 (从顶点到其本身的最短路径是零路(没有弧的路),其长度等于零);pj则是从s到j的最短路径中j点的前一点。

求解从起源点s到点j的最短路径算法的基本过程如下:1) 初始化。

起源点设置为:① ds =0, ps为空;②所有其他点: di=∞, pi=?;③标记起源点s,记k=s,其他所有点设为未标记的。

2) 检验从所有已标记的点k到其直接连接的未标记的点j的距离,并设置:d j =min[dj, dk+lkj]式中,lkj是从点k到j的直接连接距离。

3) 选取下一个点。

从所有未标记的结点中,选取dj中最小的一个i:di =min[dj, 所有未标记的点j]点i就被选为最短路径中的一点,并设为已标记的。

4) 找到点i的前一点。

从已标记的点中找到直接连接到点i的点j*,作为前一点,设置:i=j*5) 标记点i。

最小生成树---Prim算法和Kruskal算法

最小生成树---Prim算法和Kruskal算法

最⼩⽣成树---Prim算法和Kruskal算法Prim算法1.概览普⾥姆算法(Prim算法),图论中的⼀种算法,可在加权连通图⾥搜索最⼩⽣成树。

意即由此算法搜索到的边⼦集所构成的树中,不但包括了连通图⾥的所有顶点(英语:Vertex (graph theory)),且其所有边的权值之和亦为最⼩。

该算法于1930年由捷克数学家沃伊捷赫·亚尔尼克(英语:Vojtěch Jarník)发现;并在1957年由美国计算机科学家罗伯特·普⾥姆(英语:Robert C. Prim)独⽴发现;1959年,艾兹格·迪科斯彻再次发现了该算法。

因此,在某些场合,普⾥姆算法⼜被称为DJP算法、亚尔尼克算法或普⾥姆-亚尔尼克算法。

2.算法简单描述1).输⼊:⼀个加权连通图,其中顶点集合为V,边集合为E;2).初始化:V new = {x},其中x为集合V中的任⼀节点(起始点),E new = {},为空;3).重复下列操作,直到V new = V:a.在集合E中选取权值最⼩的边<u, v>,其中u为集合V new中的元素,⽽v不在V new集合当中,并且v∈V(如果存在有多条满⾜前述条件即具有相同权值的边,则可任意选取其中之⼀);b.将v加⼊集合V new中,将<u, v>边加⼊集合E new中;4).输出:使⽤集合V new和E new来描述所得到的最⼩⽣成树。

⽰例图演⽰:下⾯对算法的图例描述:3.简单证明prim算法反证法:假设prim⽣成的不是最⼩⽣成树1).设prim⽣成的树为G02).假设存在G min使得cost(G min)<cost(G0) 则在G min中存在<u,v>不属于G03).将<u,v>加⼊G0中可得⼀个环,且<u,v>不是该环的最长边(这是因为<u,v>∈G min)4).这与prim每次⽣成最短边⽭盾5).故假设不成⽴,命题得证.Kruskal算法1.概览Kruskal算法是⼀种⽤来寻找最⼩⽣成树的算法,由Joseph Kruskal在1956年发表。

浅谈算法之最小生成树Kruskal的Python实现

浅谈算法之最小生成树Kruskal的Python实现

浅谈算法之最⼩⽣成树Kruskal的Python实现⽬录⼀、前⾔⼆、树是什么三、从图到树四、解决⽣成问题五、从⽣成树到最⼩⽣成树六、实际问题与代码实现七、结尾⼀、前⾔我们先不讲算法的原理,也不讲⼀些七七⼋⼋的概念,因为对于初学者来说,看到这些术语和概念往往会很头疼。

头疼也是正常的,因为⽆端突然出现这么多信息,都不知道它们是怎么来的,也不知道这些信息有什么⽤,⾃然就会觉得头疼。

这也是很多⼈学习算法热情很⾼,但是最后⼜被劝退的原因。

我们先不讲什么叫⽣成树,怎么⽣成树,有向图、⽆向图这些,先简单点,从最基本的内容开始,完整地将这个算法梳理⼀遍。

⼆、树是什么⾸先,我们先来看看最简单的数据结构——树。

树是⼀个很抽象的数据结构,因为它在⾃然界当中能找到对应的物体。

我们在初学的时候,往往都会根据⾃然界中真实的树来理解这个概念。

所以在我们的认知当中,往往树是长这样的:上⾯这张图就是⾃然界中树的抽象,我们很容易理解。

但是⼀般情况下,我们看到的树结构往往不是这样的,⽽是倒过来的。

也就是树根在上,树叶在下。

这样设计的原因很简单,没什么特别的道理,只是因为我们在遍历树的时候,往往从树根开始,从树根往叶⼦节点出发。

所以我们倒过来很容易理解⼀些,我们把上⾯的树倒过来就成了这样:上⾯的两种画法当然都是正确的,但既然树可以正着放,也可以倒过来放,我们⾃然也可以将它伸展开来放。

⽐如下⾯这张图,其实也是⼀棵树,只是我们把它画得不⼀样⽽已。

我们可以想象⼀下,假如有⼀只⽆形的⼤⼿抓住了树根将它“拎起来”,那么它⾃然⽽然就变成了上⾯的样⼦。

然后你会发现,如果真的有这样⼤⼿,它不管拎起哪个节点,都会得到⼀棵树。

也就是说,如果树根的位置对我们不再重要的话,树其实就等价于上⾯这样的图。

那么这样的图究竟是什么图呢?它有什么性质呢?所有的图都能看成是树吗?显然这三种情况都不是树,第⼀种是因为图中的边有⽅向了。

有了⽅向之后,图中连通的情况就被破坏了。

最小生成树实验报告

最小生成树实验报告

最小生成树实验报告1.引言最小生成树(Minimum Spanning Tree,简称MST)是图论中的重要概念,在各个领域都有广泛的应用。

最小生成树是指在给定的加权连通图中,选择一个子集,使得该子集包含了所有的顶点,并且所有边的权值之和最小。

本实验主要目的是探讨最小生成树的算法并比较它们的效率和准确性。

2.实验方法本次实验使用Python编程语言实现了两种著名的最小生成树算法:Prim算法和Kruskal算法。

Prim算法是一种贪心算法,从一个顶点开始不断扩张集合,直到包含所有顶点,生成最小生成树。

Kruskal算法则是基于并查集的算法,将边按照权值排序后逐一加入生成树,同时要保证加入的边不会产生环路。

3.实验过程首先,我们从文件中读取了一张加权无向图的数据。

图的表示采用邻接矩阵的方式,即用一个二维数组来存储顶点之间的连接关系和权值。

读取完图的数据后,我们分别使用Prim算法和Kruskal算法求解最小生成树。

在Prim算法中,我们使用一个辅助数组来记录顶点是否已被访问过,然后从任意一个顶点开始,依次将与当前集合相邻的顶点加入,并选择权值最小的边。

直到所有顶点都被访问过,并形成了一个最小生成树。

在Kruskal算法中,我们首先将所有边按照权值从小到大进行排序。

然后,从权值最小的边开始,逐一将边加入生成树。

加入时,需要判断两个顶点是否在同一个连通分量中,以避免产生环路。

实验中,我们使用了Python中的heapq库来实现了堆排序,以加快Prim算法的运行速度。

4.实验结果经过实验,我们得到了图的最小生成树以及对应的权值。

实验数据显示,当图中顶点较少时,Prim算法和Kruskal算法几乎没有明显的差别。

但当图的规模增大时,Prim算法明显比Kruskal算法更快。

5.实验分析从实验结果可以看出,Prim算法和Kruskal算法都可以求解最小生成树,但在不同情况下它们的性能表现并不相同。

Prim算法适用于稠密图,因为它的时间复杂度与顶点的平方成正比;而Kruskal算法适用于稀疏图,因为它的时间复杂度与边的数量成正比。

kruskal算法求最小生成树

kruskal算法求最小生成树

kruskal算法求最小生成树课题:用kruskal算法求最小生成树。

编译工具:Visual Studio 2017kruskal算法基本思想:先构造一个只含n 个顶点、而边集为空的子图,把子图中各个顶点看成各棵树上的根结点,之后,从网的边集E中选取一条权值最小的边,若该条边的两个顶点分属不同的树,则将其加入子图,即把两棵树合成一棵树,反之,若该条边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。

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

问题:按如下连通图用kruskal算法求最小生成树。

程序源码:#include <iostream>#include <algorithm>using namespace std;const int N = 100;int nodeset[N];int n, m;struct Edge { //定义结构体.int u;int v;int w;}e[N*N];bool comp(Edge x, Edge y) { //配合sort()方法对权值进行升序。

return x.w < y.w;}void Init(int n) //对集合号nodeset数组进行初始化. {for (int i = 1; i <= n; i++)nodeset[i] = i;}int Merge(int a, int b) //将e[i].u结点传递给a; e[i].v结点传递给b. {int p = nodeset[a]; //p为a结点的集结号,int q = nodeset[b]; //q为b 结点的集结号.if (p == q) return 0; //判断结点间是否回环。

若两个结点的集结号相同,则不操作,直接返回。

for (int i = 1; i <= n; i++)//若两个结点的集结号不相同,检查所有结点,把集合号是q的改为p.{if (nodeset[i] == q)nodeset[i] = p;}return 1;}int Kruskal(int n){int ans = 0;for (int i = 1; i<=m; i++)if (Merge(e[i].u, e[i].v)){cout << "A结点:" << e[i].u << "一>B结点:" << e[i].v << endl; //输出满足条件的各结点ans += e[i].w;n--;if (n == 1)return ans;}return 0;}int main() {cout << "输入总结点数(n)和总边数(m):" << endl;cin >> n >> m;Init(n);cout << "输入结点数(u),(v)和权值(w):" << endl;for (int i = 1; i <= m; i++)cin >> e[i].u >> e[i].v >> e[i].w;sort(e+1, e + m+1, comp);int ans = Kruskal(n);cout << "最小的花费是:" << ans << endl;return 0;}源码流程解析:(1)在main()中,输入结点数n与边m,n=7,m=12。

数据结构Kruskal算法求解最小生成树

数据结构Kruskal算法求解最小生成树

数据结构Kruskal算法求解最小生成树#include<stdio.h>#include<stdlib.h>#include<malloc.h>#define MAX 100struct Node{int vertex1;int vertex2;int weight;struct Node *next;};typedef struct Node * Edge;Edge head = NULL;int visited[MAX];Edge read(){int v1, v2, w;Edge newNode = NULL, pointer = NULL;while(1){scanf("%d %d %d", &v1, &v2, &w);if(v1 == -1 || v2 == -1 || w == -1)break;newNode = (Edge)malloc(sizeof(struct Node));newNode->vertex1 = v1;newNode->vertex2 = v2;newNode->weight = w;newNode->next = NULL;pointer = head;if(pointer == NULL)head = newNode;else{if(newNode->weight < pointer->weight){newNode->next = pointer;head = newNode;}else{while(pointer != NULL && pointer->next != NULL){if(pointer->weight < newNode->weight && newNode->weight < pointer->next->weight){newNode->next = pointer->next;pointer->next = newNode;break;}pointer = pointer->next;}pointer->next = newNode;}}}return head;}void printLink(Edge edge){Edge pointer = edge;printf("\n\n图中所有边按权值递增的排序如下: \n");while(pointer != NULL){printf("[%d %d]", pointer->vertex1, pointer->vertex2);printf("(%d)",pointer->weight);if(pointer->next != NULL)printf(" ==> ");pointer = pointer->next;}printf("\n");}void kruskal(Edge edge, int vexnum){int visitedEdgeNum = 0, weight = 0;printf("\n最小生成树的路径为: \n");while(visitedEdgeNum < vexnum){if(visited[edge->vertex1] == 0 || visited[edge->vertex2] == 0){ printf("[%d %d]", edge->vertex1, edge->vertex2);printf("(%d) ",edge->weight);weight += edge->weight; visitedEdgeNum++;visited[edge->vertex1] = 1;visited[edge->vertex2] = 1;}edge = edge->next;if(edge == NULL){break;}}printf("\n\n最短路径长度为:%d \n\n", weight);}void main(){int vexnum, i;Edge edge = NULL;printf("请输入定点个数、各顶点和权值:\n输入形式如下:n i j w ... -1 -1 -1\nn 表示图的顶点个数,i j w 表示从顶点i 到顶点j 的权为w 的一条边,均以-1结尾。

最小生成树的两种算法

最小生成树的两种算法

最小生成树的两种算法包括:
1. Prim算法:
Prim算法是一种选择点加入树的算法。

首先选择任意一点作为树的第一个节点,然后枚举与它相连的所有点,将两点之间的边权记为这个点到生成树的距离,选择距离最近的点加入生成树,然后枚举与之相邻的节点,用边权更新该节点的距离,使距离等于两个节点之间的边的权重和。

再继续加入当前离生成树最近的点,在更新它相邻的点,以此类推,直到所有点全部加入生成树。

这样就求出了最小生成树。

2. Kruskal算法:
Kruskal算法也称为“加边法”。

首先把图中的所有边按代价从小到大排序,把图中的n个顶点看成独立的n棵树组成的森林,按权值从小到大选择边,所选的边连接的两个顶点应该属于两颗不同的树,则成为最小生成树的一条边,并将这两颗树合并作为一颗树。

重复以上步骤,直到所有顶点都在一颗树内或者有n-1条边为止。

这样就可以得到最小生成树。

以上信息仅供参考,可以咨询计算机专业人士或者查看专业书籍,
以获取更准确更全面的内容。

c语言最小生成树kruskal算法

c语言最小生成树kruskal算法

c语言最小生成树kruskal算法Kruskal算法是一种用于求解最小生成树的常用算法,它的时间复杂度为O(ElogE),其中E为边的数量。

本文将介绍Kruskal算法的基本原理、实现步骤以及应用场景。

一、基本原理最小生成树是指一个无向连通图中,包含所有顶点且具有最小权值和的树。

Kruskal算法通过贪心策略来逐步构建最小生成树,具体步骤如下:1. 将图中的所有边按照权值从小到大进行排序;2. 依次选取权值最小的边,如果该边的两个顶点不在同一个连通分量中,则将该边添加到最小生成树中,并将两个顶点合并为一个连通分量;3. 重复步骤2,直到最小生成树中包含了图中的所有顶点。

二、实现步骤下面通过伪代码来描述Kruskal算法的具体实现步骤:1. 初始化最小生成树的边集为空;2. 将图中的所有边按照权值从小到大进行排序;3. 遍历排序后的边集,对于每条边(u, v),进行如下判断:- 如果u和v不在同一个连通分量中,则将边(u, v)添加到最小生成树的边集中,并将u和v合并为一个连通分量;- 否则,忽略该边;4. 重复步骤3,直到最小生成树中包含了图中的所有顶点;5. 输出最小生成树的边集。

三、应用场景Kruskal算法在实际应用中有着广泛的应用场景,下面介绍两个典型的应用场景:1. 网络通信:在计算机网络中,最小生成树可以用来构建最优的网络拓扑结构,以实现高效的数据通信。

Kruskal算法可以用来求解最小生成树,从而确定网络中的最短路径,减少数据传输的时间和成本。

2. 铁路规划:在铁路交通规划中,最小生成树可以用来确定最优的铁路线路布局,以提高铁路运输的效率和安全性。

Kruskal算法可以用来求解最小生成树,从而确定铁路的建设顺序和线路规划,减少投资和施工成本。

总结:Kruskal算法是一种常用的求解最小生成树的算法,它通过贪心策略逐步构建最小生成树,具有时间复杂度较低的优势。

本文介绍了Kruskal算法的基本原理、实现步骤以及应用场景,希望读者通过本文的介绍能够对Kruskal算法有更深入的理解和应用。

图的最小生成树的实现(Kruskal算法)

图的最小生成树的实现(Kruskal算法)

数据结构课程设计设计说明书图的最小生成树的实现(Kruskal算法)学生姓名学号班级成绩指导教师计算机科学与技术系2011年 3 月4日数据结构课程设计评阅书注:指导教师成绩60%,答辩成绩40%,总成绩合成后按五级制记入。

摘要设计了一种图的最小生成树的实现程序。

本程序的算法按照克鲁斯卡尔算法的思想,采用图的邻接矩阵法存储图的顶点和边。

纳入权值最小的边作为最小生成树的一部分,如遇回路则舍弃准备纳入的边,直到图的所有顶点被遍历。

该程序采用VC++作为软件开发环境,简单易行又节省时间。

关键词:图; 最小生成树;克鲁斯卡目录1 课题描述 (1)2 问题分析和任务定义 (2)3 逻辑设计 (3)4 流程图 (4)5 程序编码 (7)6 程序调试结果 (11)7 结果分析 (13)8 总结 (14)参考文献 (15)1 课题描述本次课程设计题目是:图的最小生成树的实现(Kruskal算法)。

要求按照克鲁斯卡尔的算法思想编写一个新的程序,实现图的最小生成树的生成。

Kruskal算法就是把所有的边按权值从小到大排序,然后依次把各个点加入到最小树的集合中去,但是在加入的过程中不能有回路。

自主完成程序的编译与调试,画出流程图,并对此次课程设计过程中出现的问题和自己掌握的东西做一个详细的分析总结。

2 问题分析和任务定义本课题涉及图的创建,存储及最小生成树问题。

所谓最小生成树,就是给定一个无向图,挑选若干条边,连成一个树行图(无圈),使得所选边的权至和最小。

该程序的算法是生成图的最小生成数,而且算法必须遵循克鲁斯卡尔思想,即纳入图中权值最小的边作为最小生成树的一部分,继续纳入权值次小的边,直到图中所有顶点被遍历,如纳入边的过程中构成回路则舍弃该边,否则纳入。

3 逻辑设计该程序主要由六大块组成,包括构造最小生成树数组、排序、交换权值、构造最小生成树、查找、还有主函数。

如下图3.1所示:图3.1 程序模块图4 流程图该程序的流程图如图4.1所示:图4.1 流程图..图4.2 流程图图4.3 流程图图4.4流程图5 程序编码#include<stdio.h>#include<stdlib.h>#define M 20#define MAX 20typedef struct{int begin;int end;int weight;}edge;typedef struct{int adj;int weight;}AdjMatrix[MAX][MAX];typedef struct{AdjMatrix arc;int vexnum, arcnum;}MGraph;void CreatGraph(MGraph *);//函数申明void sort(edge* ,MGraph *);void MiniSpanTree(MGraph *);int Find(int *, int );void Swapn(edge *, int, int);void CreatGraph(MGraph *G)//构件图{int i, j,n, m;printf("请输入边数和顶点数:");scanf("%d %d",&G->arcnum,&G->vexnum);for (i = 1; i <= G->vexnum; i++)//初始化图{for ( j = 1; j <= G->vexnum; j++){G->arc[i][j].adj = G->arc[j][i].adj = 0;}}for ( i = 1; i <= G->arcnum; i++)//输入边和权值{printf("\n请输入有边的2个顶点");scanf("%d %d",&n,&m);while(n < 0 || n > G->vexnum || m < 0 || n > G->vexnum) {printf("输入的数字不符合要求请重新输入:");scanf("%d%d",&n,&m);}G->arc[n][m].adj = G->arc[m][n].adj = 1;getchar();printf("\n请输入%d与%d之间的权值:", n, m);scanf("%d",&G->arc[n][m].weight);}printf("邻接矩阵为:\n");for ( i = 1; i <= G->vexnum; i++){for ( j = 1; j <= G->vexnum; j++){printf("%d ",G->arc[i][j].adj);}printf("\n");}}void sort(edge edges[],MGraph *G)//对权值进行排序{int i, j;for ( i = 1; i < G->arcnum; i++){for ( j = i + 1; j <= G->arcnum; j++){if (edges[i].weight > edges[j].weight){Swapn(edges, i, j);}}}printf("权排序之后的为:\n");for (i = 1; i < G->arcnum; i++){printf("<< %d, %d >> %d\n", edges[i].begin, edges[i].end, edges[i].weight);}}void Swapn(edge *edges,int i, int j)//交换权值以及头和尾{int temp;temp = edges[i].begin;edges[i].begin = edges[j].begin;edges[j].begin = temp;temp = edges[i].end;edges[i].end = edges[j].end;edges[j].end = temp;temp = edges[i].weight;edges[i].weight = edges[j].weight;edges[j].weight = temp;}void MiniSpanTree(MGraph *G)//生成最小生成树{int i, j, n, m;int k = 1;int parent[M];edge edges[M];for ( i = 1; i < G->vexnum; i++){for (j = i + 1; j <= G->vexnum; j++){if (G->arc[i][j].adj == 1){edges[k].begin = i;edges[k].end = j;edges[k].weight = G->arc[i][j].weight;k++;}}}sort(edges, G);for (i = 1; i <= G->arcnum; i++){parent[i] = 0;}printf("最小生成树为:\n");for (i = 1; i <= G->arcnum; i++)//核心部分{n = Find(parent, edges[i].begin);m = Find(parent, edges[i].end);if (n != m){parent[n] = m;printf("<< %d, %d >> %d\n", edges[i].begin, edges[i].end,edges[i].weight);}}}int Find(int *parent, int f)//找尾{while ( parent[f] > 0){f = parent[f];}return f;}int main(void)//主函数{MGraph *G;G = (MGraph*)malloc(sizeof(MGraph));if (G == NULL){printf("memory allcation failed,goodbye"); exit(1);}CreatGraph(G);MiniSpanTree(G);system("pause");return 0;}6 程序调试结果程序调试结果如图6.1,图6.2所示:图6.1 结果运行图图6.2 结果运行图7 结果分析程序运行过程中出现的问题主要有:调试过程中必须以正确的格式输入图的顶点,以及边的相关信息。

最小生成树Kruskal算法+并查集实现

最小生成树Kruskal算法+并查集实现

最⼩⽣成树Kruskal算法+并查集实现今天刚掌握Kruskal算法,写下随笔。

对于稀疏图来说,⽤Kruskal写最⼩⽣成树效率更好,加上并查集,可对其进⾏优化。

Kruskal算法的步骤:1.对所有边进⾏从⼩到⼤的排序。

2.每次选⼀条边(最⼩的边),如果如果形成环,就不加⼊(u,v)中,否则加⼊。

那么加⼊的(u,v)⼀定是最佳的。

并查集:我们可以把每个连通分量看成⼀个集合,该集合包含了连通分量的所有点。

⽽具体的连通⽅式⽆关紧要,好⽐集合中的元素没有先后顺序之分,只有“属于”与“不属于”的区别。

图的所有连通分量可以⽤若⼲个不相交集合来表⽰。

⽽并查集的精妙之处在于⽤数来表⽰集合。

如果把x的⽗结点保存在p[x]中(如果没有⽗亲,p[x]=x),则不难写出结点x所在树的递归程序:find(int x) {return p[x]==x?x:p[x]=find(p[x]);}意思是,如果p[x]=x,说明x本⾝就是树根,因此返回x;否则返回x的⽗亲p[x]所在树的根结点。

既然每棵树表⽰的只是⼀个集合,因此树的形态是⽆关紧要的,并不需要在“查找”操作之后保持树的形态不变,只要顺便把遍历过的结点都改成树根的⼉⼦,下次查找就会快很多了。

如下图所⽰:设第i条边的端点序号和权值分别保存在u[i],v[i],w[i]中,⽽排序后第i⼩的边保存在r[i]中。

(间接排序是指排序的关键字是对象的代号,⽽不是对象本⾝。

)结合hdoj1863代码如下:#include <stdio.h>#include <stdlib.h>#include <algorithm>#define N 150using namespace std;int m,n,u[N],v[N],w[N],p[N],r[N];int cmp(const int i,const int j) {return w[i]<w[j];}int find(int x) {return p[x]==x?x:p[x]=find(p[x]);}int kruskal(){int cou=0,x,y,i,ans=0;for(i=0;i<n;i++) p[i]=i;for(i=0;i<m;i++) r[i]=i;sort(r,r+m,cmp);for(i=0;i<m;i++){int e=r[i];x=find(u[e]);y=find(v[e]);if(x!=y) {ans += w[e];p[x]=y;cou++;}}if(cou<n-1) ans=0;return ans;}int main(){int i,ans;while(scanf("%d%d",&m,&n)!=EOF&&m){for(i=0;i<m;i++){scanf("%d%d%d",&u[i],&v[i],&w[i]);}ans=kruskal();if(ans) printf("%d\n",ans); else printf("?\n",ans); }return 0;}。

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

#include<stdio.h>
#include<stdlib.h>
#define M 20
#define MAX 20
typedef struct
{
int begin;
int end;
int weight;
}edge;
typedef struct
{
int adj;
int weight;
}AdjMatrix[MAX][MAX];
typedef struct
{
AdjMatrix arc;
int vexnum, arcnum;
}MGraph;
void CreatGraph(MGraph *);//函数申明
void sort(edge* ,MGraph *);
void MiniSpanTree(MGraph *);
int Find(int *, int );
void Swapn(edge *, int, int);
void CreatGraph(MGraph *G)//构件图
{
int i, j,n, m;
printf("请输入边数和顶点数:\n");
scanf("%d %d",&G->arcnum,&G->vexnum);
for (i = 1; i <= G->vexnum; i++)//初始化图{
for ( j = 1; j <= G->vexnum; j++)
{
G->arc[i][j].adj = G->arc[j][i].adj = 0;
}
}
for ( i = 1; i <= G->arcnum; i++)//输入边和权值
{
printf("请输入有边的2个顶点\n");
scanf("%d %d",&n,&m);
while(n < 0 || n > G->vexnum || m < 0 || n > G->vexnum) {
printf("输入的数字不符合要求请重新输入:\n");
scanf("%d%d",&n,&m);
}
G->arc[n][m].adj = G->arc[m][n].adj = 1;
getchar();
printf("请输入%d与%d之间的权值:\n", n, m);
scanf("%d",&G->arc[n][m].weight);
}
printf("邻接矩阵为:\n");
for ( i = 1; i <= G->vexnum; i++)
{
for ( j = 1; j <= G->vexnum; j++)
{
printf("%d ",G->arc[i][j].adj);
}
printf("\n");
}
}
void sort(edge edges[],MGraph *G)//对权值进行排序{
int i, j;
for ( i = 1; i < G->arcnum; i++)
{
for ( j = i + 1; j <= G->arcnum; j++)
{
if (edges[i].weight > edges[j].weight)
{
Swapn(edges, i, j);
}
}
}
printf("权排序之后的为:\n");
for (i = 1; i < G->arcnum; i++)
{
printf("<< %d, %d >> %d\n", edges[i].begin, edges[i].end, edges[i].weight); }
}
void Swapn(edge *edges,int i, int j)//交换权值以及头和尾
{
int temp;
temp = edges[i].begin;
edges[i].begin = edges[j].begin;
edges[j].begin = temp;
temp = edges[i].end;
edges[i].end = edges[j].end;
edges[j].end = temp;
temp = edges[i].weight;
edges[i].weight = edges[j].weight;
edges[j].weight = temp;
}
void MiniSpanTree(MGraph *G)//生成最小生成树
{
int i, j, n, m;
int k = 1;
int parent[M];
edge edges[M];
for ( i = 1; i < G->vexnum; i++)
{
for (j = i + 1; j <= G->vexnum; j++)
{
if (G->arc[i][j].adj == 1)
{
edges[k].begin = i;
edges[k].end = j;
edges[k].weight = G->arc[i][j].weight;
k++;
}
}
}
sort(edges, G);
for (i = 1; i <= G->arcnum; i++)
{
parent[i] = 0;
}
printf("最小生成树为:\n");
for (i = 1; i <= G->arcnum; i++)//核心部分
{
n = Find(parent, edges[i].begin);
m = Find(parent, edges[i].end);
if (n != m)//判断是否有回路,如果有,舍弃
{
parent[m] = n;
printf("<< %d, %d >> %d\n", edges[i].begin, edges[i].end, edges[i].weight); }
}
}
int Find(int *parent, int f)//找尾
{
while ( parent[f] > 0)
{
f = parent[f];
}
return f;
}
int main(void)//主函数
{
MGraph *G;
G = (MGraph*)malloc(sizeof(MGraph));
if (G == NULL)
{
printf("memory allcation failed,goodbye");
exit(1);
}
CreatGraph(G);
MiniSpanTree(G);
system("pause");
return 0;
}
/%BD%F5%B1%F3ljb/blog/item/7bce9a339f74f049ac4b5f30.html
#include "heap.h"
#include "UFSets.h"
template <class T, class E>
void Kruskal (Graph<T, E>& G,
MinSpanTree<T, E>& MST) {
MSTEdgeNode<T, E> ed; //边结点辅助单元
int u, v, count;
int n = G.NumberOfVertices(); //顶点数
int m = G.NumberOfEdges(); //边数
MinHeap <MSTEdgeNode<T, E>> H(m); //最小堆
UFSets F(n); //并查集
for (u = 0; u < n; u++)
for (v = u+1; v < n; v++)
if (G.getWeight(u,v) != maxValue) {
ed.tail = u; ed.head = v; //插入堆
ed.cost = G.getWeight (u, v);
H.Insert(ed);
count = 1; //最小生成树边数计数
while (count < n) { //反复执行, 取n-1条边
H.Remove(ed); //退出具最小权值的边
u = F.Find(ed.tail); v = F.Find(ed.head);
//取两顶点所在集合的根u与v
if (u != v) { //不是同一集合,不连通
F.Union(u, v); //合并,连通它们
MST.Insert(ed); //该边存入MST
count++;
}
}
};。

相关文档
最新文档