离散数学--最小生成树实验报告
最小生成树 实验报告
最小生成树实验报告最小生成树实验报告一、引言最小生成树是图论中的一个重要概念,它在实际问题中有着广泛的应用。
本次实验旨在通过编程实现最小生成树算法,并通过实验数据对算法进行分析和评估。
二、算法介绍最小生成树算法的目标是在给定的带权无向图中找到一棵生成树,使得树上所有边的权重之和最小。
本次实验我们选择了两种经典的最小生成树算法:Prim 算法和Kruskal算法。
1. Prim算法Prim算法是一种贪心算法,它从一个顶点开始,逐步扩展生成树的规模,直到包含所有顶点为止。
算法的具体步骤如下:(1)选择一个起始顶点,将其加入生成树中。
(2)从与生成树相邻的顶点中选择一个权重最小的边,将其加入生成树中。
(3)重复上述步骤,直到生成树包含所有顶点。
2. Kruskal算法Kruskal算法是一种基于并查集的贪心算法,它首先将图中的边按权重从小到大进行排序,然后逐个加入生成树中,直到生成树包含所有顶点为止。
算法的具体步骤如下:(1)将图中的边按权重从小到大进行排序。
(2)逐个加入边,如果该边的两个顶点不在同一个连通分量中,则将其加入生成树中。
(3)重复上述步骤,直到生成树包含所有顶点。
三、实验过程本次实验我们使用C++语言实现了Prim算法和Kruskal算法,并通过随机生成的图数据进行了测试。
1. Prim算法的实现我们首先使用邻接矩阵表示图的结构,然后利用优先队列来选择权重最小的边。
具体实现过程如下:(1)创建一个优先队列,用于存储生成树的候选边。
(2)选择一个起始顶点,将其加入生成树中。
(3)将与生成树相邻的顶点及其边加入优先队列。
(4)从优先队列中选择权重最小的边,将其加入生成树中,并更新优先队列。
(5)重复上述步骤,直到生成树包含所有顶点。
2. Kruskal算法的实现我们使用并查集来维护顶点之间的连通关系,通过排序后的边序列来逐个加入生成树中。
具体实现过程如下:(1)将图中的边按权重从小到大进行排序。
最小生成树 实验报告
最小生成树(Minimum Spanning Tree)实验报告1. 实验目的本实验旨在通过实践掌握最小生成树算法的基本原理和实现方法。
最小生成树是图论中的一个重要概念,用于解决具有权重的连通图的最优路径问题。
通过本实验,我们将学习如何使用最小生成树算法找到一棵连接图的所有节点且总权重最小的树。
2. 实验原理最小生成树是一个连通图的一种生成树,它的所有边的权重之和最小。
最小生成树的求解算法有多种,其中两种常用的算法是 Prim 算法和 Kruskal 算法。
2.1 Prim 算法Prim 算法是一种贪心算法,从一个节点开始,逐步扩展最小生成树的边。
具体步骤如下: 1. 选择一个起始节点作为最小生成树的根节点。
2. 在当前最小生成树的所有节点中选择一个与该树相连接的权重最小的边,将其加入最小生成树。
3. 将该节点标记为已访问。
4. 重复步骤 2 和步骤 3,直到所有节点都被访问。
2.2 Kruskal 算法Kruskal 算法也是一种贪心算法,通过不断选择权重最小的边来构建最小生成树。
具体步骤如下: 1. 对所有边按照权重进行排序。
2. 依次选择权重最小的边,如果该边的两个端点不在同一个连通分量中,则将该边加入最小生成树,并将这两个端点合并到同一个连通分量中。
3. 重复步骤 2,直到所有节点都在同一个连通分量中,即最小生成树构建完成。
3. 实验步骤本实验将使用 Prim 算法和 Kruskal 算法分别求解给定图的最小生成树。
3.1 数据准备首先,我们需要准备一个具有权重的连通图作为实验数据。
假设该图有 n 个节点和 m 条边,我们可以使用邻接矩阵或邻接表来表示这个图。
3.2 Prim 算法求解最小生成树1.首先,选择一个起始节点作为最小生成树的根节点,并将该节点标记为已访问。
2.初始化一个空的最小生成树,用于存储最终的结果。
3.重复以下步骤,直到所有节点都被访问:1.在当前最小生成树的所有节点中选择一个与该树相连接的权重最小的边,将其加入最小生成树。
最小生成树算法实验报告
最小生成树算法实验报告【实验报告】最小生成树算法实验一、实验目的本次实验旨在研究最小生成树算法,通过对比不同的算法,并对实验结果进行分析,探索最小生成树算法的优劣势和适应场景。
二、实验过程1.算法介绍本次实验中我们将使用两种最小生成树算法:普里姆算法和克鲁斯卡尔算法。
- 普里姆算法(Prim算法):从一个顶点开始,不断在剩下的顶点中选择到当前已有的最小生成树的距离最小的边,将该边的另一个顶点加入树中,直到所有的顶点都加入树中。
- 克鲁斯卡尔算法(Kruskal算法):首先将所有边按照权值从小到大进行排序,然后以最小权值的边开始,依次选择权值最小且不会形成环路的边,直到找到n-1条边为止,其中n为顶点数。
2.实验步骤首先,我们使用Python语言实现了普里姆算法和克鲁斯卡尔算法。
然后,我们构造了一些测试用例,包括不同规模的图和不同权值分布的图。
最后,我们对实验结果进行对比分析。
三、实验结果1.测试用例设计我们设计了三个测试用例,分别为小规模图、中规模图和大规模图,具体如下:-小规模图:顶点数为5的图,权值随机分布。
-中规模图:顶点数为50的图,权值随机分布。
-大规模图:顶点数为100的图,权值随机分布。
2.实验结果分析我们的实验结果如下表所示:算法,小规模图,中规模图,大规模图:-------:,:------:,:------:,:------:普里姆算法,13,455,703从实验结果可以看出,对于小规模图和中规模图,普里姆算法的运行时间明显低于克鲁斯卡尔算法。
但是对于大规模图,克鲁斯卡尔算法的运行时间与普里姆算法的运行时间差距不大,甚至略小于普里姆算法。
这是因为克鲁斯卡尔算法中排序边的时间复杂度为O(ElogE),而普里姆算法中筛选最小距离的边的时间复杂度为O(V^2)。
综上所述,普里姆算法适用于较小规模的图,而克鲁斯卡尔算法适用于较大规模的图。
四、实验总结本次实验研究了最小生成树算法,通过对比实验结果,我们发现不同算法在不同规模的图上的表现有所差异。
最小生成树数据结构实验报告
摘要最小生成树是数据结构中图的一种重要应用,在图中对于n个顶点的连通网可以建立许多不同的生成树,最小生成树就是在所有生成树中总的权值最小的生成树。
本课程设计是以邻接矩阵作为图的存储结构,分别采用Prim和Kruskal算法求最小生成树。
Kruskal算法和Prim算法是求最小生成树的常用算法它们分别适用于稠密图和稀疏图。
最小生成树的应用非常的广,如矿井通风设计和改造最优化方面以及如何搭建最短的网络线缆, 构建造价最低的通讯网络等等一系列的应用。
关键词:最小生成树,邻接矩阵,Kruskal算法,Prim算法目录一、引言 (3)二、设计目的与任务 (4)2.1课程设计目的 (4)2.2课程设计的任务 (4)三、设计方案 (4)3.1需求分析 (4)3.2数据结构分析 (4)3.2.1抽象数据类型(ADT)如下 (4)3.2.2基本操作 (5)3.2.3存储结构 (5)3.3最小生成树的算法分析 (7)3.3.1主函数模块代码......................... 错误!未定义书签。
3.3.2邻接矩阵定义模块代码 (7)3.3.3创建链接矩阵模块代码 (7)3.3.4最小生成树Prim算法及代价模块代码...... 错误!未定义书签。
3.3.5最小生成树kruskal算法及代价模块代码 (8)四、调试分析与体会 (9)五、运行结果 (10)六、结论 (16)七、参考文献 (16)一、引言《数据结构》是计算机科学与技术专业和信息管理与信息系统专业的必修课之一,是一门综合性的专业基础课。
本课程较系统地介绍了软件设计中常用的数据结构以及相应的实现算法,如线性表、栈、队列、树和二叉树,图、检索和排序等,并对性能进行分析和比较,内容非常丰富。
本课程设计我们要解决的问题是图最小生成树问题。
要用到图的先相关数据结构和求最小生成树的两种数据结构算法普里姆算法和克鲁斯卡尔算法,以及储存图的边和点的邻接矩阵。
实验5最小生成树算法的设计与实现(报告)
实验5 最小生成树算法的设计与实现一、实验目的1、根据算法设计需要, 掌握连通图的灵活表示方法;2、掌握最小生成树算法,如Prim、Kruskal算法;3、基本掌握贪心算法的一般设计方法;4、进一步掌握集合的表示与操作算法的应用。
二、实验内容1、认真阅读算法设计教材和数据结构教材内容, 熟习连通图的不同表示方法和最小生成树算法;2、设计Kruskal算法实验程序。
有n个城市可以用(n-1)条路将它们连通,求最小总路程的和。
设计测试问题,修改并调试程序, 输出最小生成树的各条边, 直至正确为止。
三、Kruskal算法的原理方法边权排序:1 3 14 6 23 6 41 4 52 3 53 4 52 5 61 2 63 5 65 6 61. 初始化时:属于最小生成树的顶点U={}不属于最小生成树的顶点V={1,2,3,4,5,6}2. 根据边权排序,选出还没有连接并且权最小的边(1 3 1),属于最小生成树的顶点U={1,3},不属于最小生成树的顶点V={2,4,5,6}3. 根据边权排序,选出还没有连接并且权最小的边(4 6 2),属于最小生成树的顶点U={{1,3},{4,6}}(还没有合在一起,有两颗子树),不属于最小生成树的顶点V={2,5}4. 根据边权排序,选出还没有连接并且权最小的边(3 6 4),属于最小生成树的顶点U={1,3,4,6}(合在一起),不属于最小生成树的顶点V={2,5}5. 根据边权排序,选出还没有连接并且权最小的边(3 6 4),属于最小生成树的顶点U={1,2,3,4,6},,不属于最小生成树的顶点V={5}6. 根据边权排序,选出还没有连接并且权最小的边(3 6 4),属于最小生成树的顶点U={1,2,3,4,5,6}此时,最小生成树已完成四、实验程序的功能模块功能模块:bool cmp(Edge a,Edge b); //定义比较方法x);//在并查集森林中找到x的祖先int g etfa(intint s ame(int x,int y); //判断祖先是否是同一个,即是否联通 void merge(int x,int y); //合并子树,即联通两子树sort(e+1,e+m+1,cmp); //对边按边权进行升序排序详细代码:#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#define M AXN_E 100000#define M AXN_V 100000using namespace std;struct Edge{int f m,to,dist;//边的起始顶点,边的到达顶点,边权}e[MAXN_E];int f a[MAXN_V],n,m; //顶点数组,顶点总数,边总数 //定义比较,只是边权比较bool cmp(Edge a,Edge b){return a.dist < b.dist;}//查找x的祖先是在并查集森林中找到x的祖先x){//getfaint g etfa(intreturn fa[x];if(fa[x]==x)else r eturn fa[x] = getfa(fa[x]);}//判断祖先是否是同一个,即是否联通int s ame(int x,int y){return getfa(x)==getfa(y);}//合并两棵树void merge(int x,int y){int f ax=getfa(x),fay=getfa(y);fa[fax]=fay;}int m ain(){int i;cout<<"请输入顶点数目和边数目:"<<endl;cin>>n>>m;//n为点数,m为边数//输出顶点信息cout<<"各个顶点值依次为:"<<endl;for(i=0;i<n;i++){fa[i]=i;if(i!=0)cout<<fa[i]<<" ";}cout<<endl;cout<<"请输入边的信息(例子:1 4 5 从顶点1到顶点4的边权为5)"<<endl;for(i=1;i<=m;i++)用边集数组存放边,方便排序和调用 cin>>e[i].fm>>e[i].to>>e[i].dist;//sort(e+1,e+m+1,cmp); //对边按边权进行升序排序表示目前的点共存在于多少个集合中,初始情况是每 int r st=n,ans=0;//rst个点都在不同的集合中for(i=1;i<=m && rst>1;i++){int x=e[i].fm,y=e[i].to;函数是查询两个点是否在同一集合中 if(same(x,y))continue;//sameelse{函数用来将两个点合并到同一集合中 merge(x,y);//mergerst--;//每次将两个不同集合中的点合并,都将使rst值减1这条边是最小生成树中的边,将答案加上边权 ans+=e[i].dist;//}}cout<<ans;return 0;}五、测试数据和相应的最小生成树Input:6 101 2 61 3 11 4 52 3 52 5 63 4 53 5 63 6 44 6 25 6 6Putout:18生成树为:七、思考题1、微软面试题一个大院子里住了50户人家,每家都养了一条狗,有一天他们接到通知说院子里有狗生病了,并要求所有主人在发现自己家狗生病的当天就要把狗枪杀掉。
离散数学大作业——编程实现最小生成树
离散数学大作业——编程实现最小生成树学院:电子工程学院班级:021051学号:*********名:***一、最小生成树概念:设G=(V,E)是无向连通带权图,即一个网络。
E中每条边(v,w)的权为c[v,w]。
所有生成树G’上各边权的总和最小的生成树称为G的最小生成树。
二、prim算法(贪心思想)设图G =(V,E),其生成树的顶点集合为U。
1.把v0放入U。
2.在所有u∈U,v∈V-U的边(u,v)∈E中找一条最小权值的边,加入生成树。
3.把2找到的边的v加入U集合。
如果U集合已有n个元素,则结束,否则继续执行2其算法的时间复杂度为O(n^2)三、程序源代码# include<stdio.h># include<malloc.h># define m 6# define n 11 typedef struct {int i,tag;char s;}vertice;typedef struct {int a,b,tag;int weight;}edge;vertice v[m];edge e[n];void inititate();void sort();void chuli();int biaoji( edge *s); void print();void main() {inititate();sort();chuli();print();}void inititate() {int i;printf("输入图的%d个顶点:\n",m);for(i=0;i<m;i++) {v[i].i=i+1;v[i].tag=0;scanf("%c",&v[i].s);getchar();}printf("\n输入%d条边的两端顶点及权:\n",n);for(i=0;i<n;i++) {scanf("%d %d %d",&e[i].a,&e[i].b,&e[i].weight);e[i].tag=0;}}int biaoji( edge *s) {int i,j;i=s->a;j=s->b;if(v[i].tag==0 || v[j].tag==0) {v[i].tag=1;v[i].tag=1;s->tag=1;return 1;}return 0;}void print() {int i,j=0;printf("\n最小生成树的边为:\n");for(i=0;i<n&&j<m-1;i++)if(e[i].tag==1) {printf("<%d-%d> ",e[i].a,e[i].b);j++;}printf("\n\n");}void sort() {edge s;int i,j;for(i=0;i<n-1;i++) {for(j=i+1;j<n;j++) {if(e[i].weight>e[j].weight) {s=e[i];e[i]=e[j];e[j]=s;}}}}void chuli() {int i,j=0;edge *s;for(i=0;i<n&&j<m;i++) {s=&e[i];if(biaoji(s)==1)j++;}}四、实验结果输入图的6个顶点:1 2 3 4 5 6输入11条边的权及两端顶点:1 2 11 4 61 6 91 3 112 3 22 4 33 5 83 6 74 5 104 6 45 6 5最小生成树的边为:<1-2> <2-3> <2-4> <4-6> <5-6> Press any key to continue。
数据结构实验报告-最小生成树(精选5篇)
数据结构实验报告-最小生成树(精选5篇)第一篇:数据结构实验报告-最小生成树电子科技大学实验报告学生姓名:XXX 学号:20***指导教师:刘峤实验地点:信软楼306实验时间:5月17日一、实验室名称:软件实验室二、实验项目名称:数据结构与算法—图三、实验学时:4四、实验原理:Kruskal 算法是一种按照图中边的权值递增的顺序构造最小生成树的方法。
其基本思想是:设无向连通网为G=(V,E),令G 的最小生成树为T,其初态为T=(V,{}),即开始时,最小生成树T 由图G 中的n 个顶点构成,顶点之间没有一条边,这样T 中各顶点各自构成一个连通分量。
然后,按照边的权值由小到大的顺序,考察G 的边集E 中的各条边。
若被考察的边的两个顶点属于T 的两个不同的连通分量,则将此边作为最小生成树的边加入到T 中,同时把两个连通分量连接为一个连通分量;若被考察边的两个顶点属于同一个连通分量,则舍去此边,以免造成回路,如此下去,当T 中的连通分量个数为1 时,此连通分量便为G 的一棵最小生成树。
如教材153页的图4.21(a)所示,按照Kruskal 方法构造最小生成树的过程如图4.21 所示。
在构造过程中,按照网中边的权值由小到大的顺序,不断选取当前未被选取的边集中权值最小的边。
依据生成树的概念,n 个结点的生成树,有n-1 条边,故反复上述过程,直到选取了n-1 条边为止,就构成了一棵最小生成树。
五、实验目的:本实验通过实现最小生成树的算法,使学生理解图的数据结构存储表示,并能理解最小生成树Kruskal 算法。
通过练习,加强对算法的理解,提高编程能力。
六、实验内容:(1)假定每对顶点表示图的一条边,每条边对应一个权值;(2)输入每条边的顶点和权值;(3)输入每条边后,计算出最小生成树;(4)打印最小生成树边的顶点及权值。
七、实验器材(设备、元器件):八、数据结构及程序#include #include #include typedefstruct {intvex;intgno;}TVex,*TpVex;typedefstruct {intvhead, vtail;intwght;intflag;}TEdge,*TpEdge;typedef struct{TpVex VexList;TpEdge EdgeList;int nvex, nedge;}TGraph, *TpGraph;void begin(TpGraph G){ int i;for(i=1;i<=G->nvex;i++){G->VexList[i-1].gno=i;G->EdgeList[i-1].flag=0;} } int findmin(TpGraph G){ int i,j;int minwght=G->EdgeList[0].wght;for(i=0,j=-1;inedge;i++){ PC机一台,装有C/C++语言集成开发环境。
最小生成树的Kruskal算法实验报告
大连民族学院计算机科学与工程学院实验报告实验题目:最小生成树的Kruskal算法课程名称:离散数学实验类型:□演示性□验证性□操作性■设计性□综合性专业:软件工程班级:111学生姓名:xx学号:xx实验日期:2012年12月6-28日实验地点:金石滩校区机房201 实验学时:10学时实验成绩:指导教师:焉德军姜楠2012年12月28 日[实验原理]设所给定无向连通加权图具有n个结点,m条边,首先,将各条边的权按从小到大的顺序排序。
然后依次将这些边按所给图的结构放到生成树中去。
如果在放置某一条边时,使得生成树形成回路,则删除这条边。
这样,直至生成树具有n-1条边时,我们所得到的就是一棵最小生成树。
[实验内容]给定无向连通加权图,编程设计求出其一棵最小生成树。
[实验目的]通过算法设计并编程实现求出给定无向连通加权图的一棵最小生成树,加深学生对求最小生成树的Kruskal算法的理解。
[实验步骤](1)边依小到大顺序得l1,l2,…,lm。
(2)置初值:⇒∅S,0⇒i,1⇒j。
(3)若i=n-1,则转(6)。
(4)若生成树边集S并入一条新的边lj之后产生的回路,则j+1⇒j,并转(4)。
(5)否则,i+1⇒i;l j⇒S(i);j+1⇒j,转(3)。
(6)输出最小生成树S。
(7)结束。
具体程序的C++实现如下:#include<iostream>using namespace std;const int MaxVertex = 20;const int MaxEdge = 100;const int MaxSize = 100;struct EdgeType{int from;int to;int weight;};struct EdgeGraph{char vertex[MaxVertex];EdgeType edge[MaxEdge];int vertexNum;int edgeNum;};int FindRoot(int parent[], int v);void InputInfo();void Kruskal(EdgeGraph G){int vex1,vex2,f,t;int i,num;int parent[MaxVertex];for(i=0; i<G.vertexNum; i++){parent[i] = -1;}for(num =0,i=0; i<G.edgeNum; i++){vex1 = FindRoot(parent, G.edge[i].from);vex2 = FindRoot(parent, G.edge[i].to);if(vex1 != vex2){cout << "(" << G.edge[i].from << "," << G.edge[i].to << ")" << endl;f = G.edge[i].from;t = G.edge[i].to;cout << "(" << G.vertex[f] << "," << G.vertex[t] << ")" << " Weight: " << G.edge[i].weight << endl;cout << endl;parent[vex2] = vex1;num++;if(num == G.vertexNum-1) return;}}return;}int FindRoot(int parent[], int v){int t;t = v;if(parent[t] > -1){t = parent[t];}return t;}void InputInfo(){EdgeGraph G;cout << "Please input vertexNum , edgeNum: " << endl;cin >> G.vertexNum >> G.edgeNum;cout << "Please input the information of edges:" << endl;for(int i=0; i<G.vertexNum; i++){cin >> G.vertex[i];}cout << "Please input this edge attaches two vertices subscript and its weight" << endl;for(int j=0; j<G.edgeNum; j++){cin >> G.edge[j].from >> G.edge[j].to >> G.edge[j].weight;}Kruskal(G);}int main(){InputInfo();system("pause");return 0;}实验过程中遇到的问题及解决过程比如不知道如何存储边集数组,以及比知道如何声明一些变量,函数和怎样去调用Kruskal函数……解决:通过设置结构体EdgeType与结构体EdgeGraph的联合来存储边集,因为在刚开始我在主函数中用EdgeGraph声明变量G,来作为形参去调用Kruskal(G),编译时就会警告未被初始化的G,的程序出错,后来我将Kruskal(G)在InputInfo() 中调用,因为InputInfo()函数中声明了变量G,并使得G初始化,从而是的程序能正常运行。
离散数学试验报告
离散数学实验报告姓名:学号:班级:实验地点:实验时间:Word文档1实验目的和要求运用最小生成树思想和求最小生成树程序解决实际问题。
实际问题描述如下:八口海上油井相互间距离如下表,其中1号井离海岸最近,为5km。
问从海岸经1 号井铺设油管把各井连接起来,怎样连油管长度最短(为便于检修,油管只准在油井处分叉)?「到 2 3 4 5 6 7 81 1.3 2.1 0.9 0.7 1.8 2.0 1.820.9 1.8 1.2 2.8 2.3 1.13 2.6 1.7 2.5 1.9 1.040.7 1.6 1.5 0.950.9 1.1 0.860.6 1.070.52实验环境和工具实验环境:Windows 7旗舰版工具:Dev-C++ 5.8.33实验过程3.1算法流程1Word i=0;j=0;惠档exnum=8;结束3.2程序核心代码〃油管铺设问题Prim 算法实现#include <iostream> #include<iomanip> using namespace std; #define MAXV 10#define INF 32767 //INF 表示8 typedef int InfoType; typedef struct{int no; InfoType info; } VertexType;typedef struct{〃图的定义float edges[MAXV][MAXV]; 〃邻接矩阵 int vexnum;//顶点数 VertexType vexs[MAXV]; //存放顶点信息 } MGraph;//图的邻接矩阵类型〃顶点编号 //顶点其他信息 〃顶点类型Word文档/*输出邻接矩阵g*/void DispMat(MGraph g){int i,j;for (i=0;i<g.vexnum;i + +){for (j=0;j<g.vexnum;j + +)if (g.edges[i][j] = = INF)cout<<setw⑹<<“8";elsecout<<setw(6)<<g.edges[i][j];cout<<endl;))void prim(MGraph g,int v){ //从顶点V0 出发,按Prim 算法构造G的最小生成树//输出最小生成树的每条边及其权值float Vlength[MAXV];int i, j, k;int cloest[MAXV];float min;float sum = 0.0;Word文档for(i=0;i<g.vexnum;i ++){Vlength[i]=g.edges[v][i];cloest[i]=v;)for(i = 1;i<g.vexnum;i + +){min = INF; //min为其中最大的一条边二MAXVfor(j=0;j<g.vexnum;j + +){〃找n-1 条边if(Vlength[j]!=0&&Vlength[j]<min){min=Vlength[j];k=j;))cout<<" 连接油<”<<cloest[k] + 1<<”,”<<k+1<<">"<<“ 长度为:"<<min<<endl;sum + = min;Vlength[k]=0;Vlength[cloest[k]]=0;for(j=0;j<g.vexnum;j + +){ 〃选择当前代价最小的边if(g.edges[k][j]!=0&&g.edges[k][j]<Vlength[j]){Vlength[j]=g.edges[k][j];cloest[j]=k;Word文档)cout<<"管道总长度为:"<<sum<<endl;)int main()(int i,j,u=3;MGraph g;float A[MAXV][10];g.vexnum=8;for (i=0;i<g.vexnum;i + +)for (j=0;j<g.vexnum;j + +)A[i][j] = INF;A[0][1] = 1.3; A[0][2]=2.1; A[0][3]=0.9;A[0][4]=0.7; A[0][5] = 1.8; A[0][6]=2.0;A[0][7] = 1.8; A[1][2]=0.9; A[1][3] = 1.8;A[1][4] = 1.2; A[1][5]=2.8; A[1][6]=2.3;A[1][7] = 1.1; A[2][3]=2.6; A[2][4] = 1.7;A[2][5]=2.5; A[2][6] = 1.9; A[2][7] = 1.0;A[3][4]=0.7; A[3][5] = 1.6; A[3][6] = 1.5;A[3][7]=0.9; A[4][5]=0.9; A[4][6] = 1.1;Word文档A[4][7]=0.8; A[5][6]=0.6; A[5][7] = 1.0;A[6][7]=0.5;for (i=0;i<g.vexnum;i + +)for (j=0;j<g.vexnum;j + +)A[j][i]=A[i][j];for (i=0;i<g.vexnum;i + +) /*建立图的邻接矩阵*/ for (j=0;j<g.vexnum;j + +)g.edges[i][j]=A[i][j];cout<<endl;cout<<”各油井间距离:\n";DispMat(g);cout<<endl;cout<<"最优铺设方案:\n";prim(g,0);cout<<endl;return 0;)3.3运行结果Word文档exited after O.06836 seconds 3.4 运行结果分析程序实现了输出需要铺设管道的油井编号,并给出了每条管道长度以及总长度,基 本实现了题目要求。
离散数学实验报告材料
离散数学实验报告姓名:学号:班级:实验地点:实验时间:1实验目的和要求运用最小生成树思想和求最小生成树程序解决实际问题。
实际问题描述如下:八口海上油井相互间距离如下表,其中1号井离海岸最近,为5km。
问从海岸经1号井铺设油管把各井连接起来,怎样连油管长度最短(为便于检修,油管只准在油井处分叉)?2实验环境和工具实验环境:Windows 7 旗舰版工具:Dev-C++ 5.8.33实验过程3.1算法流程图3.2程序核心代码//油管铺设问题 Prim算法实现#include <iostream>#include<iomanip>using namespace std;#define MAXV 10#define INF 32767 //INF表示∞typedef int InfoType;typedef struct{int no; //顶点编号InfoType info; //顶点其他信息} VertexType; //顶点类型typedef struct{ //图的定义float edges[MAXV][MAXV]; //邻接矩阵int vexnum; //顶点数VertexType vexs[MAXV]; //存放顶点信息} MGraph; //图的邻接矩阵类型/*输出邻接矩阵g*/void DispMat(MGraph g){int i,j;for (j=0;j<g.vexnum;j++)if (g.edges[i][j]==INF)cout<<setw(6)<<"∞";elsecout<<setw(6)<<g.edges[i][j];cout<<endl;}}void prim(MGraph g,int v){ //从顶点V0出发,按Prim算法构造G的最小生成树//输出最小生成树的每条边及其权值float Vlength[MAXV];int i, j, k;int cloest[MAXV];float min;float sum = 0.0;for(i=0;i<g.vexnum;i++){Vlength[i]=g.edges[v][i];cloest[i]=v;}min=INF; //min为其中最大的一条边=MAXVfor(j=0;j<g.vexnum;j++){ //找n-1条边if(Vlength[j]!=0&&Vlength[j]<min){min=Vlength[j];k=j;}}cout<<"连接油井<"<<cloest[k]+1<<","<<k+1<<">"<<"长度为:"<<min<<endl;sum+=min;Vlength[k]=0;Vlength[cloest[k]]=0;for(j=0;j<g.vexnum;j++){ //选择当前代价最小的边if(g.edges[k][j]!=0&&g.edges[k][j]<Vlength[j]){ Vlength[j]=g.edges[k][j];cloest[j]=k;}}}cout<<"管道总长度为:"<<sum<<endl;}int main(){int i,j,u=3;MGraph g;float A[MAXV][10];g.vexnum=8;for (i=0;i<g.vexnum;i++)for (j=0;j<g.vexnum;j++)A[i][j]=INF;A[0][1]=1.3; A[0][2]=2.1; A[0][3]=0.9;A[0][4]=0.7; A[0][5]=1.8; A[0][6]=2.0;A[0][7]=1.8; A[1][2]=0.9; A[1][3]=1.8;A[1][4]=1.2; A[1][5]=2.8; A[1][6]=2.3;A[1][7]=1.1; A[2][3]=2.6; A[2][4]=1.7;A[2][5]=2.5; A[2][6]=1.9; A[2][7]=1.0;A[3][4]=0.7; A[3][5]=1.6; A[3][6]=1.5;A[3][7]=0.9; A[4][5]=0.9; A[4][6]=1.1;A[4][7]=0.8; A[5][6]=0.6; A[5][7]=1.0;A[6][7]=0.5;for (i=0;i<g.vexnum;i++)for (j=0;j<g.vexnum;j++)A[j][i]=A[i][j];for (i=0;i<g.vexnum;i++) /*建立图的邻接矩阵*/ for (j=0;j<g.vexnum;j++)g.edges[i][j]=A[i][j];cout<<endl;cout<<"各油井间距离:\n";DispMat(g);cout<<endl;cout<<"最优铺设方案:\n";prim(g,0);cout<<endl;return 0;}3.3运行结果3.4运行结果分析程序实现了输出需要铺设管道的油井编号,并给出了每条管道长度以及总长度,基本实现了题目要求。
求最小生成树(Kruskal算法)实验报告【范本模板】
学生实验报告学院:软件与通信工程学院课程名称:离散数学(软件)专业班级:12软件2班姓名:杨滨学号:0123707学生实验报告(2) 学生姓名杨滨 学号 0123707 同组人 实验项目 求最小生成树(Kruskal 算法)□必修 □选修 □演示性实验 □验证性实验 □操作性实验 □综合性实验 实验地点W101 实验仪器台号 指导教师 赵晓平 实验日期及节次 2013。
12。
12(四) 89A 节一、实验综述1、实验目的及要求(1)了解求最优化问题的贪心算法,了解贪心法的基本要素,学会如何使用贪心策略设计算法;(2)掌握Prim 算法和Kruskal 算法的思想及两者之间的区别;(3)编写程序,分别利用Prim 算法和Kruskal 算法实现,求出最小代价生成树,输出构成最小代价生成树的边集.实验要求:给出如右图的边权图,求最小生成树.认真完成实验题,能正确运行,提交实验报告并上传程序,实验报告要求写出操作步骤、结果、问题、解决方法、体会等.2、实验仪器、设备或软件计算机、VC++6。
0、office 、相关的操作系统等.二、实验过程(实验步骤、记录、数据、分析)#include<stdio.h 〉#define VERTS 6struct edge {int from ,to; //起顶点,终顶点int find ,val ; //标记,顶点间边长struct edge *next; };typedef struct edge node;node *find_min_cost(node *);void min_tree(node *);√ √int v[VERTS+1]={0};//记录顶点即下标,值即出现过的次数void main(){int data[10][3]={{1,0,6},{0,3,5},{3,5,2},{5,4,6},{4,1,3},{2,1,5},{2,0,1},{2,3,5},{2,5,4},{2,4,6}};//表示有10条线,例如{1,0,6}表示1和0距离为6node *head,*ptr,*new_node;head=NULL;printf(”Add graph:\n”);for (int i=0; i<10; i++){for (int j=1;j<=VERTS;j++){if (data[i][0]==j){new_node=new node;new_node—>from=data[i][0];new_node—〉to=data[i][1];new_node—〉val=data[i][2];new_node—>find=0;new_node-〉next=NULL;if (head==NULL){head=new_node;head-〉next=NULL;ptr=head;}else{ptr-〉next=new_node;ptr=ptr-〉next;}}}}for (ptr=head; ptr!=NULL; ptr=ptr—>next)printf("Begin[%d]\tEnd[%d]\t\tPath[%d]\n”,ptr-〉from,ptr—〉to,ptr-〉val);printf("\nAdd Min Tree:\n”);min_tree(head);putchar('\n');}void min_tree(node *head) //建立最小生成树{node *ptr,*tmptr;int result=0;//布尔值,是否做出输出结果for (ptr=head;ptr!=NULL;ptr=ptr—〉next) //遍历十条边{tmptr=find_min_cost(head); //找出最小边顶点v[tmptr-〉from]++;//当前起点已选自加1次v[tmptr—〉to]++; //当前终点已选自加1次if (v[tmptr—>from]〉1 &&v[tmptr->to]>1){/*这个IF语句就是一个防止生成树中有回路;因为v[tmptr->from]与v[tmptr—〉to]都出现过一次,这棵树的叶子结点都为1,所以当两个结点同时为2时,就形成回路*/v[tmptr—〉from]——;v[tmptr—>to]--;result=1;}else result=0;if (result==0)printf("Begin[%d]\tEnd[%d]\t\tPath[%d]\n",tmptr—〉from,tmptr->to,tmptr—〉val);}}node *find_min_cost(node *head) //最小边查找{int min_val=100;node *ptr,*tmptr;for (ptr=head;ptr!=NULL;ptr=ptr-〉next){if (ptr->val<min_val && ptr-〉find==0) //当当前边最小时并当前顶点没有被选择过{min_val=ptr->val;tmptr=ptr;}} //整个循环遍历完毕找到最小连min_valtmptr->find=1; //并标记该顶的边已选择return tmptr;}三、结论1、实验结果2、分析讨论在编写这个程序时,我们先要非常熟悉kruskal算法,kruskal算法总共选择n—1条边,所使用的贪婪准则是:从剩下的边中选择一条不会产生环路的具有最小耗费的边加入已选择的边的集合内。
最小生成树实验报告
一、实验目的1. 通过上机程序,进一步加深对最小生成树的理解。
2. 掌握Kruskal算法。
3. 学会用程序解决离散数学中的问题。
4. 增强我们编写程序的能力。
二、实验内容求带权无向联通平面图的最小生成树三、实验环境我的实验依旧是在实验环境下完成的,而所设计的程序也在这个环境下通过了编译,运行和测试。
四、实验原理和实现过程利用Kruskal算法求最小生成树,原理如下:1.选取最小权边e1,置边数j 1.2.i=n-1结束,否则转c。
3.设已经选择的边为e1,e2,......,ei,在G中选取不同于e1,e2, (i)边,使{e1,e2,……,ei,ei+1}中无回路且ei+1是满足此条件的最小边。
4.i i+1,转b。
根据这个,还有以下思路:由G生成的最小生成树T所包含的边的集合1.按非降序权重将E中的边排序2.建立n个单元素集(每个顶点一个)3.最小生成树的边集合T初始为空4 .while |T|<n-15. 令e(x,y)为E中的下一条边6. if包含x的集合不是与包含y的集合不是同一个集合 then7. 将e(x,y)加入到T8. 将包含x的集合和包含y的集合合并9. end ifwhile五、实验源代码及分析#include<>struct Edge{int from, to, weight; rom); o);if(x!=y) rom, edge[k].to, edge[k].weight); rom, &edge[i].to, &edge[i].weight); eight>edge[j].weight){temp=edge[i];edge[i]=edge[j];edge[j]=temp;}printf("The minimum spanning tree is:\n");Kruskal(); //调用Kruskal算法return 0;}其中运用seek函数找出当前端点所在集合编号。
最小生成树实验报告
最小生成树实验报告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算法适用于稀疏图,因为它的时间复杂度与边的数量成正比。
【报告】最小生成树算法实验报告
【关键字】报告最小生成树算法➢问题描述设G=(V,E)是一个无向连通带权图,E中每条边(v,w)的权为c(v,w)。
如果G的一个子图G`是一棵包含G的所有顶点的书,则称G`为G的生成树。
生成树上各边权的总和称为该生成树的耗费,在G的所有生成树中,耗费最小的生成树就称为G的最小生成树。
给定一个无向连通带权图,构造一个最小生成树。
➢设计思想利用Prim算法求最小生成树,Prim算法是利用贪心策略设计的算法。
设G=(V,E)是一个连通带权图,V={1,2,…,n}。
构造G的一棵最小生成树的Prim算法的基本思想是:首先置U={1},然后,只要U是V的真子集,就做如下的贪心选择:选取满足条件i∈U,j∈V-U,且使c(i,j)达到最小的边(i,j),并将顶点j添加到U中。
这个过程一致进行到U=V时为止。
在这个过程中选取到的所有边恰好构成G的一棵最小生成树。
➢时间复杂度Prim算法的Pascal语言描述如下:Procedure PRIM(c:array[1..n,1..n] of real);Varlowcost:array[1..n] of real;closest:array[1..n] of integer;i,j,k,min,integer;begin(1)for i:=2 to n do(2)begin{初始化,此时U只含有顶点1}(3)lowcost[i]:=c[1,i];(4)Closest[i]:=1;(5)end;(6)for i:=2 to n do(7)begin {寻找顶点分别在V-U与U中边权最小的边}(8)min:=lowcost[i];(9)j:=i;(10)For k:=2 to n do(11)If lowcost[k]<min then(12)Begin(13)Min:=lowcost[k];(14)j:=k;(15)End;(16)print(j,closest[j]);{输出找到的边}(17)Lowcost[j]:=∞;{将j添加到U}(18)For k:=2 to n do {调整lowcost和closest}(19)if(c[j,k]<lowcost[k])and(lowcost[k]< ∞)then(20)Begin(21)Lowcost[k]:=c[j,k];(22)Closest[k]:=j;(23)End(24)End(25)End;{PRIM}上述过程中第(6)~(24)行的for循环要执行n-1次,每次执行时,第(10)~(15)行和第(18)~(23)行的for循环都要O(n)时间,所以Prim算法所需的计算时间为O(n)。
最小生成树实验报告
最小生成树实验报告最小生成树(Minimum Spanning Tree,MST)是图论中的一个重要概念,用于在一个连通带权无向图中找到一个子图,使得这个子图是一个树(即无环连通图),并且所有边的权值之和最小。
最小生成树在诸多领域有着广泛的应用,如网络设计、电力传输等。
在本次实验中,我们实现了最小生成树算法,并将其运用到多个实际问题上。
下面将依次介绍算法原理、实现过程、实验结果以及对实验的进一步改进。
1.算法原理Kruskal算法的基本思想是,首先将所有边按照权值从小到大排序,然后从最小的边开始,逐一加入生成树,直到生成树包含了所有的顶点。
在加入一条边时,需要判断这条边将两个顶点连通起来是否会形成环,如果不会则加入生成树。
Prim算法的基本思想是,从一个顶点开始,逐步加入生成树的顶点,每次加入一个顶点时,选择一个离生成树最近的点,并将这个点加入生成树。
通过不断的选择顶点和加入边,最终得到最小生成树。
2.实现过程首先,我们实现了图的数据结构和边的数据结构。
在图的数据结构中,我们定义了图的顶点数和边数,并用邻接矩阵来表示图的连接情况。
边的数据结构包含了两个顶点和边的权值。
其次,我们实现了两种算法。
对于Kruskal算法,我们首先将所有边按照权值从小到大进行排序。
然后,逐个加入边,判断是否形成环。
如果不会形成环,则将该边加入生成树。
最后,我们使用并查集数据结构来判断两个顶点是否连通。
对于Prim算法,我们首先选择一个起点作为生成树的初始顶点,并将其加入生成树。
然后,每次选择一个离生成树最近的顶点,并将其加入生成树,同时更新其他顶点到生成树的距离。
最后,所有顶点都被加入生成树后,得到最小生成树。
3.实验结果我们在实验中选择了不同大小的图进行测试。
经过对比,我们发现Kruskal算法和Prim算法得到的最小生成树结果是一致的,但是Kruskal 算法的时间复杂度要稍高于Prim算法。
具体的结果如下:对于一个边数为10的图,我们得到了如下最小生成树:1-2-4-5-3总权重为12对于一个边数为20的图,我们得到了如下最小生成树:2-1-4-5-3总权重为16对于一个边数为30的图2-1-4-5-6-7-3总权重为22从实验结果来看,无论是规模较小的图还是规模较大的图,我们都能够得到最小生成树,并且所得到的结果是正确的。
最小生成树prim算法实验报告
最小生成树prim算法实验报告最小生成树Prim算法实验报告引言:最小生成树(Minimum Spanning Tree,简称MST)是图论中的一个重要概念,意为在一个连通图中找到一棵生成树,使得树上所有边的权值之和最小。
Prim算法是一种常用的解决MST问题的贪心算法。
本实验旨在通过实际操作和观察,深入理解Prim算法的原理与过程。
实验目的:1. 理解Prim算法的基本原理;2. 掌握Prim算法的具体实现过程;3. 利用Prim算法求解最小生成树问题;4. 分析Prim算法的时间复杂度。
实验过程:1. 实验环境搭建:在实验开始前,我们需要搭建合适的实验环境。
首先,我们选择一种编程语言,如Python或C++,来实现Prim算法。
其次,我们需要准备一个图的数据集,可以是随机生成的或者是从现实问题中提取的。
最后,我们需要一个用于可视化的工具,以便观察Prim算法的执行过程和结果。
2. Prim算法实现:Prim算法的核心思想是从一个顶点开始,逐步扩展生成树,直到包含所有顶点为止。
具体实现过程如下:a. 初始化一个空的生成树,选择一个起始顶点;b. 在剩余的顶点中,选择与生成树距离最近的顶点,并将其加入生成树;c. 更新生成树与剩余顶点的距离,如果存在更短的路径,则更新;d. 重复步骤b和c,直到生成树包含所有顶点。
3. Prim算法求解最小生成树问题:利用Prim算法求解最小生成树问题的步骤如下:a. 根据实验环境搭建中准备的图数据集,构建图的邻接矩阵或邻接表表示;b. 选择一个起始顶点,将其加入生成树;c. 重复以下步骤,直到生成树包含所有顶点:i. 从生成树中选择一个顶点v,找到与v相连的顶点中距离最小的顶点u; ii. 将顶点u加入生成树,并将(u, v)边加入生成树的边集;iii. 更新生成树与剩余顶点的距离,如果存在更短的路径,则更新。
实验结果与分析:我们通过实验环境搭建和Prim算法实现,成功求解了多个最小生成树问题。
最小生成树2
最小生成树(实验报告)1.功能要求:1.在n各城市间建设通讯网络,用最小成本架设线路。
2.要求建立N个城市间通信网络;3.增加删除城市节点;求最小生成树,输出各节点及边上的权值。
2.数据要求:1.原始数据:城市的代码,为int类型数值,由而且仅有0开始递增,范围0—99;两城市间的架线的成本,为unsigned类型数值,范围为0—9999 。
2.输入的形式为(vi,vj,weight),vi,vj分别为两城市的代码。
weight为城市vi与城市vj之间架线的成本。
3.建立存储边的链表,存储结点记录信息为边的权值和该边所连接的城市代码。
4.建立存储所有信息的图。
3.数据处理:1.追加城市:输入数据后,可以追加数据,在原基础上加入新的数据。
2.删除城市:分为按边删除和按城市结点删除。
按边删除:输入一条边及连接的城市的代码,在链表中找出匹配的结点删除。
按城市结点删除:输入一个城市代码,在链表中找到与该点有关的边删除。
3.输出邻接矩阵:对输入的数据建立图,以邻接矩阵的形式显示出来,没有连接的城市间权值设置为10000,连接的城市间权值设为边的权值。
4.选出最优架线线路:利用kruskal方法在图中选择最小生成树,既城市间的最优架线线路,输出格式为(vi,vj,weight),vi,vj为所需连接的两城市代码,weight为这两个城市间架线的成本。
二、概要设计系统设计图:数据存储结构(变量均为全局变量):int n; //记录城市点数量int m; //记录城市边的数量typedef struct LNode //定义一个链表结点,四个属性{unsigned weight; //边的权值int vi,vj; //边的两个端点的城市代码struct LNode *next; //指针的下一个结点};int cs[100][100]; //存储由链表中数据生成的图int ChengShi[100]; //在kruskal方法中记录已经连接到的城市LNode *LX= new LNode; //存储边的链表的头指针LNode *P; //存储边的链表的为指针该系统三个子系统:数据增加和数据输入:void shuju_shuru()功能:1.确定城市数目n和边数目m。
最小生成树算法实验报告_2
作业1最小生成树的生成算法1.1算法应用背景在实际生活中, 图的最小花费生成树问题有着广泛的应用。
例如, 用图的顶点代表城市, 顶点与顶点之间的边代表城市之间的道路或通信线路, 用边的权代表道路的长度或通信线路的费用, 则最小花费生成树问题, 就表示为城市之间最短的道路或费用最小的通信线路问题。
其中普里姆算法是使用贪婪法策略设计的典型算法。
1.2算法原理在一给定的无向图G = (V, E) 中, (u, v) 代表连接顶点u 与顶点v 的边(即), 而w(u, v) 代表此边的权重, 若存在T 为E 的子集(即)且为无循环图, 使得的w(T) 最小, 则此T 为G 的最小生成树。
许多应用问题都是一个求无向连通图的最小生成树问题。
例如:要在n个城市之间铺设光缆, 主要目标是要使这n 个城市的任意两个之间都可以通信, 但铺设光缆的费用很高, 且各个城市之间铺设光缆的费用不同;另一个目标是要使铺设光缆的总费用最低。
这就需要找到带权的最小生成树。
1.3算法描述1)最小生成树之普里姆算法描述:令G=(V,E,W), 为简单期间, 令顶点集为V={0,1,2…, n-1}。
假定与顶点i, j相关联的边为ei, j, ei, j的权用c[i][j]表示, T是最小花费生成树的边集。
这个算法维护两个顶点集合S 和N, 开始时: 令T=Ф,S={0},N=V-S。
然后, 进行贪婪选择, 选取i∈S, j∈N, 并且c[i][j]最小的i和j;并使S=S∪S{j},N=N-{j},T=T∪{ei, j}.重复上述步骤, 直到N为空, 或找到n-1条边为止。
此时, T中的边集, 就是所要求取的G中的最小花费生成树。
由此, 可描述普里姆算法的步骤如下:(1)T=Ф, S={0},N=V-S。
(2)如果N为空, 算法结束;否则, 转步骤(3)。
(3)寻找使i∈S, j∈N, 并且c[i][j]最小的i和j。
(4)S=S∪S{j},N=N-{j},T=T∪{ei, j};转步骤(2)。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一、实验目的:掌握图的存储表示和以及图的最小生成树算法。
二、实验内容:1.实现图的存储,并且读入图的内容。
2.利用克鲁斯卡尔算法求网络的最小生成树。
3.实现构造生成树过程中的连通分量抽象数据类型。
4.以文本形式输出对应图的最小生成树各条边及权值。
三、实验要求:1.在上机前写出全部源程序;2.能在机器上正确运行程序;3.用户界面友好。
需求分析:1、利用克鲁斯卡尔算法求网的最小生成树;2、以用户指定的结点为起点,分别输出每种遍历下的结点访问序列;3、输入为存在边的顶点对,以及它们之间的权值;输出为所得到的邻接矩阵以及按权排序后的边和最后得到的最小生成树;克鲁斯卡尔算法:假设WN=(V,{E}) 是一个含有n 个顶点的连通网,按照构造最小生成树的过程为:先构造一个只含n 个顶点,而边集为空的子图,之后,从网的边集 E 中选取一条权值最小的边,若该条边的两个顶点分属不同的树,则将其加入子图,反之,若该条边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。
依次类推,直至只有一棵树,也即子图中含有n-1条边为止。
测试数据:自行指定图进行运算四、详细设计源程序#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;}运行结果:五、实验总结(结果分析和体会)在编程时,因为考虑的情况比较多,所以容易造成错误和遗漏,为了避免这些问题的出现,可以先用笔把所有的程序在纸上,然后再根据列表编写程序,这样不仅简单易懂,还避免了一些不必要的错误。
编写完程序后进行调试,发现有很多错误,其中也不乏一些基本的小错误,所以程序写完后进行静态检查是必不可少的,其次是逻辑上的错误,对于这些错误,只能再认真检查整个程序,这就要求我们在编程时考虑要周到,或者可以请其他同学帮忙检查。
通过这次对算术表达式求值的设计,让我自己对克鲁斯卡尔算法的运用更深刻,能够基本上很好的运用克鲁斯卡尔算法来解决一些问题。
不过从中也发现了很多问题,那就是虽然课本知识的掌握还不错,但是上机编程的能力还有所匮乏,应该加强这方面的锻炼,通过上机的实践来提升对基础知识的理解。
还有就是应该多和同学交流,比如一个相同的问题,我有我的编程思路,他有他的,通过相互的交流、讨教,可以获得更广的知识信息,开拓思维,自己不懂的通过咨询就可以掌握。