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

合集下载

求无向图的最小生成树算法——Prim与Kruskal

求无向图的最小生成树算法——Prim与Kruskal

求无向图的最小生成树算法——Prim与Kruskal一.Prim算法1.算法思想对于图G=(V,E),用Prim算法求最小生成树T=(S,TE)的流程如下① 初始化:设S、TE为空集,任选节点K加入S。

② 选取一条权值最小的边(X,Y),其中X∈S,且not (Y∈S)即,选取一条权值最小的、连接着S中一点与S外一点的边。

将Y加入S中,边(X,Y)加入TE中重复② 直到V=S即所有G中的点都在S中,此时的T为G的最小生成树。

由此流程可见,Prim算法求最小生成树时任何时候的T都是一颗树。

2.实现显然,Prim算法的主要运行时间花在过程②的选边中。

看起来复杂度是O(VE)=O(V^3)不是么,效率也太低了吧……为了比较快速地选边,我们用两个数组lowcost、closest动态地维护每一个点到S的最短距离。

在某一状态下,lowcost[i]表示所有与i相连且另一端点在S中的边中的权值最小值,closest[i]表示在S中且与i相连的点中与i之间距离最小的点。

显然,lowcost[i]=w(i,closest[i])。

需要注意的是两个数组记录的都是边而不是路径。

若i没有边直接连向S,则lowcost[i]=∞。

另外,若i已在S 中,则lowcost[i]=0。

设出发点为x。

初始时对于任意k∈V,closest[k]=x,lowcost[k]=w(k,x)【w(i,j)表示i、j间的距离。

初始化时,若两点间没有边则w(i,j)赋为一个足够大的整数(如maxint),并且所有点到自身的距离赋为0,即w(i,i)=0】每一次找出lowcost中不为0的最小值lowcost[i],然后把i加入S(即lowcost[i]:=0),然后对于图中所有点k,若w(k,i)<lowcost[k],则把lowcost[k]赋为w(k,i),把closest[k]赋为i。

【由于s中所有点的lowcost都为0,所以只影响到s以外的点】以上操作重复|V|-1次结束。

最小生成树算法

最小生成树算法

最小生成树之克鲁斯卡尔(Kruskal)算法、普里姆(prim)算法分类:算法 2012-01-04 11:091159人阅读评论(0)收藏举报算法问题描述:在一个具有几个顶点的连通图G中,如果存在子图G'包含G中所有顶点和一部分边,且不形成回路,则称G'为图G的生成树,其中代价最小的生成树则称为最小生成树。

例如,设有下图G,找出连接图G所有顶点(v1,v2,v3,v4,v5,v6)的边,且这些边的权重之和最小。

那么如何生成该最小生成树呢?两个经典算法是普里姆 (Prim)算法和克鲁斯卡(Kruskal )算法。

克鲁斯卡尔(Kruskal)算法:克鲁斯卡尔(Kruskal)算法是以图上的边为出发点依据贪心策略逐次选择图中最小边为最小生成树的边,且所选的当前最小边与已有的边不构成回路。

在图G中,首先选择最小的边(V2,V3),(V4,V5),(V2,V4),因为(V4,V6)和(V5,V6)权重相等,所以可以任选其中一条(这也表明最小生成树不是唯一的)。

同样的道理,选择权重为5的边(V3,V5)(V2,V1),因为(V3,V5)和(V2,V3),(V2,V4),(V4,V5)构成了回路,所以舍弃(V3,V5)保留(V2,V1)。

这时该子图G‘已经包含了图G的所有的边,算法结束。

得到的最小生成树如下图:伪代码: Kruskal(G,W)1、按照权重从小到大顺序排序G的边{e1,e2,e3,e4,e5,...,em};2、for i = 1to m do3、如果ei的两个端点不在同一个连通分支,则将ei加到T中;算法特点:时间复杂度为O(eloge)(e为网中边数),适合于求稀疏的网的最小生成树。

普里姆(Prim)算法:普里姆(Prim)算法是以图上的顶点为出发点,逐次选择到最小生成树顶点集距离最短的顶点为最小生成树的顶点,并加入到该顶点集,直到包含所有的顶点。

在图G中,选择顶点V1加入到顶点集S,连接S中顶点的边为(V1,V2)(V1,V3),选择最小的即(V1,V2),并将V2加入到顶点集S。

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

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

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

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

算法是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为上次保存的最小边)就变得必要了。

克鲁斯卡尔算法的时间复杂度

克鲁斯卡尔算法的时间复杂度

克鲁斯卡尔算法的时间复杂度
第一段:克鲁斯卡尔算法是一种求解最小生成树问题(MinimumSpanningTreeProblem)和求最短路径问题(ShortestPathProblem)的算法,是图论中最常用的算法之一。


有效地找到一幅给定的加权图中的最小生成树,并对相关的最短路径问题提供了优化的解决方案。

本文将讨论克鲁斯卡尔算法的时间复杂度,包括它的最佳情况和最坏情况。

第二段:克鲁斯卡尔算法的时间复杂度在最佳情况下是线性的,即O(n)。

具体而言,如果一个图中存在一个可以完全覆盖所有边的
最小生成树,则克鲁斯卡尔算法只需要遍历一次图来找到最小生成树,所以它的时间复杂度是O(n)。

第三段:然而,在最坏情况下,克鲁斯卡尔算法的时间复杂度是平方的,即O(n2)。

这是因为最坏情况下,算法将遍历图中的所有边,一共有O(n2)个边,这样它将在遍历完所有边之后才能完成寻找最小生成树的过程,所以它的时间复杂度是O(n2)。

第四段:此外,克鲁斯卡尔算法的时间复杂度还可能受到图的形状和连接方式的影响,这可能会严重影响算法的运行时间。

例如,如果一个图的边比较多,但是连接方式却比较规则,这样算法能够更快地找到最小生成树,导致克鲁斯卡尔算法的时间复杂度低于最坏情况下的O(n2)。

第五段:总而言之,克鲁斯卡尔算法的时间复杂度由图的状况决定。

它在最佳情况下是线性的,即O(n),在最坏情况下则是平方的,
即O(n2)。

然而,它的时间复杂度还可能受到图的形状和连接方式的影响,有时可能低于最坏情况下的O(n2)。

kruskal算法求最小生成树

kruskal算法求最小生成树

数据结构课程设计Kruskal算法求最小生成树学院:班级:学号;姓名;指导老师;完成日期:目录(一)需求分析———————————(二)概要设计———————————(三)详细设计———————————(四)主函数设计—————————(五)经验体会——————————- (六)源代码及调试分析————————1、需求分析运用kruskal算法求最小生成树最短路径:①输入任意源点,求到其余顶点的最短路径。

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

2、概要设计首先要确定图的存储形式。

经过的题目要求的初步分析,发现该题的主要操作是路径的输出,因此采用数组(邻接矩阵)的方法构造无向图,比较方便以后的编程。

从而求得最小生成树。

3、函数详细设计(1)构造无向图本题中为了能够求得最小生成树,先要构造无向图,并且用领结矩阵的形式表现出来。

void Create(MGraph &G) //采用数组(邻接矩阵)表示法,构造无向图G。

{int i,j,k,w;char v1[10],v2[10];scanf("%d%d",&G.vexnum,&G.arcnum); //输入定点数和边数for(i=0; i<G.vexnum; i++)scanf("%s", G.vexs[i]);for(i=0; i<G.vexnum; i++) //初始化邻接矩阵{for(j=0; j<G.vexnum; j++)G.arcs[i][j] = INF;}for(k=0; k<G.arcnum; k++) //构造邻接矩阵{scanf("%s%s%d",v1,v2,&w); //输入一条边依附的顶点及权值i = Locate(G,v1); //确定v1在G中的位置j = Locate(G,v2); //确定v2在G中的位置G.arcs[i][j] = w; //弧<v1,v2>的权值G.arcs[j][i] = w; //弧<v2,v1>是权值}for(i=0; i<G.vexnum; i++){for(j=0; j<G.vexnum; j++){printf("%6d ",G.arcs[i][j]);}printf("\n");}}(2) kruskal算法。

克鲁斯卡尔算法伪代码

克鲁斯卡尔算法伪代码

克鲁斯卡尔算法伪代码克鲁斯卡尔算法是一个用于求解最小生成树的算法。

最小生成树(Minimum Spanning Tree, MST)指的是在一张无向图G中找到一个树T,使得T中的边权之和最小。

克鲁斯卡尔算法的基本思路是将所有边按照权值从小到大排序,然后依次选取这些边,如果选取的边之间没有形成环,就将该边加入到最小生成树中去。

这样,直到最小生成树中有n-1条边为止,就得到了最小生成树。

1. 将边按照权值从小到大排序。

2. 初始化一个并查集,即每个点都是一个单独的子集。

3. 遍历排好序的边,依次将边加入最小生成树中。

4. 对于每条边,检查该边的两个端点是否在同一个子集中,如果不在同一个子集中,则将它们合并成一个子集,同时将这条边加入最小生成树中。

5. 直到最小生成树中有n-1条边为止。

下面是使用Java语言实现克鲁斯卡尔算法的代码示例://边的类定义class Edge implements Comparable<Edge> {int u; // 边的起点int v; // 边的终点int w; // 边的权值// 构造函数public Edge(int u, int v, int w) {this.u = u;this.v = v;this.w = w;}//并查集的类定义class UnionFind {int[] parent;int[] rank;//查找父节点public int find(int p) {while (p != parent[p]) {parent[p] = parent[parent[p]]; //路径压缩p = parent[p];}return p;}//判断两个节点是否在同一个集合中public boolean connected(int p, int q) {return find(p) == find(q);}}//求解最小生成树public void solve() {Collections.sort(edges); //按照权值从小到大排序UnionFind uf = new UnionFind(V); //初始化并查集Kruskal kruskal = new Kruskal(V, edges);kruskal.solve();System.out.println("最小生成树的边为:");for (Edge e : kruskal.mst) {System.out.println(e.u + " - " + e.v + " : " + e.w);}}输出结果如下:最小生成树的边为: 0 - 2 : 13 - 5 : 21 - 4 : 30 - 1 : 62 -3 : 5。

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

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

的最小生成树算法Prim和Kruskal算法Prim和Kruskal算法是求解最小生成树的两种常用算法。

最小生成树指的是在一个连通图中,找到一棵包含所有顶点的生成树,使得树上边的权重之和最小。

Prim算法基于贪心思想,从一个起始顶点开始,逐步向其他顶点扩展,每次选择权重最小的边连接已经选中的顶点和未选中的顶点。

具体步骤如下:1. 初始化一个空的集合S,用于存放已经选中的顶点。

2. 从图中任选一个顶点作为起始顶点,并将其加入集合S。

3. 重复以下步骤,直到集合S包含了所有顶点:a. 在未加入集合S的顶点中,找到与集合S中顶点相连的边中权重最小的边。

b. 将该边加入生成树中,并将与该边相连的顶点加入集合S。

4. 生成的树即为最小生成树。

Kruskal算法是基于边的权重排序的思想。

具体步骤如下:1. 初始化一个空的集合S,用于存放已经选中的边。

2. 将图中的所有边按照权重从小到大排序。

3. 重复以下步骤,直到生成的树中包含了所有顶点-1条边(其中顶点的数量为n):a. 从排序后的边列表中选取一条最小权重的边。

b. 若该边的两个顶点不在同一连通分量中,将该边加入生成树中。

c. 否则,舍弃该边,继续选择下一条边。

4. 生成的树即为最小生成树。

值得注意的是,在构建最小生成树时,如果图不是连通图,那么最小生成树就不存在。

Prim算法的时间复杂度为O(V^2),其中V表示顶点的数量。

在稠密图中效果较好。

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

在稀疏图中效果较好。

这两种算法在实际应用中都有一定的局限性。

Prim算法适合处理边稠密、顶点稀疏的图,而Kruskal算法适合处理边稀疏、顶点稀疏的图。

在选择使用算法时,需要根据具体问题的特点进行权衡。

最小生成树算法Prim和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。

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

目录1.需求分析 (2)1.1 设计题目 (2)1.2 设计任务及要求 (2)1.3课程设计思想 (2)1.4 程序运行流程 (2)1.5软硬件运行环境及开发工具 (2)2.概要设计 (2)2.1流程图 (2)2.2抽象数据类型MFSet的定义 (3)2.3主程序 (4)2.4抽象数据类型图的定义 (4)2.5抽象数据类型树的定义 (5)3.详细设计 (7)3.1程序 (7)4.调试与操作说明 (10)4.1测试结果 (10)4.2调试分析 (11)5.课程设计总结与体会 (11)5.1总结 (11)5.2体会 (11)6. 致谢 (12)7. 参考文献 (12)1.需求分析1.1 设计题目:最小生成树1.2 设计任务及要求:任意创建一个图,利用克鲁斯卡尔算法,求出该图的最小生成树。

1.3 课程设计思想:Kruskal算法采用了最短边策略(设G=(V,E)是一个无向连通网,令T=(U,TE)是G的最小生成树。

最短边策略从TE={}开始,每一次贪心选择都是在边集E中选择最短边(u,v),如果边(u,v)加入集合TE中不产生回路,则将边(u,v)加入边集TE中,并将它在集合E中删去。

),它使生成树以一种任意的方式生长,先让森林中的树木随意生长,每生长一次就将两棵树合并,最后合并成一棵树。

1.4程序运行流程:1)提示输入顶点数目;2)接受输入,按照项目要求产生边权值的随机矩阵;然后求解最小生成树;3)输出最小生成树并且退出;1.5 软硬件运行环境及开发工具:VC2.概要设计2.1流程图开始定义数据类型定义图定义树定义图的顶点数和边数Kruskal算法主程序图1流程图2.2抽象数据类型MFSet的定义:ADT MFSet {数据对象:若设S是MFSet型的集合,则它由n(n>0)个子集Si(i = 1,2...,n)构成,每个子集的成员代表在这个子集中的城市。

数据关系:S1 U S2 U S3 U... U Sn = S, Si包含于S(i = 1,2,...n)Init (n): 初始化集合,构造n个集合,每个集合都是单成员,根是其本身。

rank 数组初始化0Find(x):查找x所在集合的代表元素。

即查找根,确定x所在的集合,并路径压缩。

Merge(x, y):检查x与y是否在同一个集合,如果在同一个集合则返回假,否则按秩合并这两个集合并返回真。

}2.3主程序:int main(){初始化;while (条件){接受命令;处理命令;}return 0;}2.4抽象数据类型图的定义如下:ADT Graph{数据对象V:V是具有相同特性的数据元素的集合,成为顶点集。

数据关系R:R={VR} VR={<v,w>|v,w∈V且P(v,w),<v,w>表示从v 到w的弧,谓词P(v,w)定义了弧<v,w>的意义或信息}基本操作P:CreateGraph(&G,V,VR);初始条件:V是图的顶点集,VR是图中弧的集合。

操作结果:按V和的VR定义构造图G。

DestoryGraph(&G);初始条件:图G存在。

操作结果:销毁图G。

LocateVex(G,u);初始条件:图G存在,u和G中是顶点有相同特征。

操作结果:若G中存在顶点u,则返回该顶点在图中位置;否则返回其他信息。

GetVex(G,v);初始条件:图G存在,v是G中某个顶点。

操作结果:返回v的值。

PutVex(&G,v,value);初始条件:图G存在,v是G中某个顶点。

操作结果:对V赋值value,FirstAdjVex(G,v);初始条件:图G存在,v是G中某个顶点。

操作结果:返回v的第一个邻接顶点。

若顶点在G中没有顶点,则返回“空”。

NextAdjVex(G,v,w);初始条件:图G存在,v是G中某个顶点,w是v的邻接顶点。

操作结果:返回v的(相对于w的)下一个邻接顶点。

若w是v的最后一个邻接顶点,则返回“空”。

InsertVex(&G,v);初始条件:图G存在,v和途中顶点有相同特征。

操作结果:在图G中添加新顶点v。

DeleteVex(&G,v);初始条件:图G存在,v是G中某个顶点。

操作结果:删除G中顶点v及其相关的弧。

InsertArc(&G,v,w);初始条件:图G存在,v和w是G中两个顶点。

操作结果:在G中添加弧<v,w>,若G是无向的,则还增添对称弧<v,w>。

DeleteArc(&G,v,w);初始条件:图G存在,v和w是G中两个顶点。

操作结果:在G中删除弧<v,w>,若G是无向的,则还删除对称弧<v,w>。

DFSTravrese(G,Visit());初始条件:图G存在,Visit是顶点的应用函数。

操作结果:对图进行深度优先遍历。

在遍历过程中对每个顶点调用函数Visit一次且仅一次。

一旦Visit()失败,则操作失败。

BFSTravrese(G,Visit());初始条件:图G存在,Visit是顶点的应用函数。

操作结果:对图进行广度优先遍历。

在遍历过程中对每个顶点调用函数Visit 一次且仅一次。

一旦Visit()失败,则操作失败。

}ADT Graph2.5抽象数据类型树的定义如下:ADT Tree{数据对象D:D是具有相同特性数据元素的集合。

数据关系R:若D为空集,则称为空树;若D仅含一个元素数据,则R为空集,否则R={H},H是如下二元关系:(1)在D中存在唯一的称为根的数据元素root,它在关系H 下无前驱;(2)若D-{root}≠Φ,则存在D-{root}的一个划分D1,D2,…,D m(m>0),对任意j≠k(1≤j,k≤m)有D j∩D k=Φ,且对任意的I(1≤i≤m),惟一存在数据元素x i∈D i有<root,x i>∈H;(3)对应于D-{root}的划分,H-{<root,x1>,…,<roor,x m>}有惟一的一个划分H1,H2,…,H m(m>0),对任意j≠k(1≤j,k≤m)有H j∩H k=Φ,且对任意I(1≤i≤m),H i是D i上的二元关系,(D i,{H i})是一棵符合本定义的树,称为跟root的子树。

基本操作P:InitTree(&T);操作结果:构造空树T。

DestoryTree(&T);初始条件:树T存在。

操作结果:销毁树T。

CreateTree(&T,definition);初始条件:definition给出树T的定义。

操作结果:按definition构造树T。

ClearTree(&T);初始条件:树T存在。

操作结果:将树T清为空树。

TreeEmptey(T);初始条件:树T存在。

操作结果:若T为空树,则返回TRUE,否则FALSE。

TreeDepth(T);初始条件:树T存在。

操作结果:返回T的深度。

Root(T);初始条件:树T存在。

操作结果:返回T的跟。

Value(T,cur_e);初始条件:树T存在,cur_e是T中某个结点。

操作结果:返回cur_e的值。

Assign(T,cur_e,value);初始条件:树T存在,cur_e是T中某个结点。

操作结果:结点cur_e赋值为value。

Parent(T,cur_e);初始条件:树T存在,cur_e是T中某个结点。

操作结果:若cur_e是T的非根结点,则返回它的双亲,否则函数值为“空”。

LeftChild(T,cur_e);初始条件:树T存在,cur_e是T中某个结点。

操作结果:若cur_e是T的非叶子结点,则返回它的最左子,否则返回“空”。

RightSibling(T,cur_e);初始条件:树T存在,,cur_e是T中某个结点。

操作结果:若cur_e有右兄弟,则返回它的右兄弟,否则函数值为“空”。

InsertChild(&T,&p,I,c);初始条件:树T存在,P指向T中某个结点,1≤i≤p所指向的结点度数+1,非空树c与T不相交。

操作结果:插入c为T中p指结点的第i棵子树。

DeleteChild(&T,&p,i);初始条件:树T存在,p指向T中某个结点,1≤i≤p指结点的度。

操作结果:删除T中p所指结点的第i棵子树。

TraverseTree(T,Visit());初始条件:树T存在,Visit是对结点操作的应用函数。

操作结果:按某种次序对T的每个结点调用函数visit()一次且至多一次。

一旦vista()失败,则操作失败。

}ADT Tree3.详细设计3.1程序:如下#include<stdio.h>#include<stdlib.h>#include<string.h>#define MAX_NAME 5#define MAX_VERTEX_NUM 30typedef char Vertex[MAX_NAME];/*顶点名字数组*/typedef int AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];/*邻接矩阵*/typedef struct /*定义图*/{Vertex vexs[MAX_VERTEX_NUM];AdjMatrix arcs;int vexnum,arcnum;}MGraph;int LocateVex(MGraph *G,Vertex u){int i;for(i=0;i<G->vexnum;++i)if(strcmp(G->vexs[i],u)==0)return i;return -1;}void CreateGraph(MGraph *G){int i,j,k,w;Vertex va,vb;printf("请输入无向网G的顶点数和边数(以空格作为间隔): \n");scanf("%d %d",&G->vexnum,&G->arcnum);printf("请输入%d个顶点的名字(小于%d个字符):\n",G->vexnum,MAX_NAME);for(i=0;i<G->vexnum;++i) /*构造顶点集*/scanf("%s",G->vexs[i]);for(i=0;i<G->vexnum;++i) /*初始化邻接矩阵*/for(j=0;j<G->vexnum;++j)G->arcs[i][j]=0x7fffffff;printf("请输入%d条边的顶点1 顶点2 权值(以空格作为间隔):\n",G->arcnum);for(k=0;k<G->arcnum;++k){scanf("%s%s%d%*c",va,vb,&w);i=LocateVex(G,va);j=LocateVex(G,vb);G->arcs[i][j]=G->arcs[j][i]=w; /*对称*/}}void kruskal(MGraph G){FILE *fpt;fpt = fopen("9.txt","w");/*打开文档,写入*/fprintf(fpt,"最小生成树的各条边为:\n");int i,j;int k=0,a=0,b=0,min=G.arcs[a][b],min_out;printf("最小生成树的各条边为:\n");while(k<G.vexnum-1){for(i=0;i<G.vexnum;++i)for(j=i+1;j<G.vexnum;++j)if(G.arcs[i][j]<min){min=G.arcs[i][j];a=i;b=j;}min_out=min;min=G.arcs[a][b]=0x7fffffff;printf("%s-%s-%d\n",G.vexs[a],G.vexs[b],min_out);fprintf(fpt,"%s-%s-%d\n",G.vexs[a],G.vexs[b],min_out);k++;}fclose(fpt);}void main(){MGraph g;CreateGraph(&g);kruskal(g);}4. 调试与操作说明4.1测试结果:如下图图2测试结果1图3测试结果24.2调试分析本程序利用克鲁斯卡尔算法求最小生成树数据结构清晰因而调试比较顺利。

相关文档
最新文档