数据结构 实验8 最小生成树
最小生成树 实验报告
最小生成树实验报告最小生成树实验报告一、引言最小生成树是图论中的一个重要概念,它在实际问题中有着广泛的应用。
本次实验旨在通过编程实现最小生成树算法,并通过实验数据对算法进行分析和评估。
二、算法介绍最小生成树算法的目标是在给定的带权无向图中找到一棵生成树,使得树上所有边的权重之和最小。
本次实验我们选择了两种经典的最小生成树算法: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)一、引言《数据结构》是计算机科学与技术专业和信息管理与信息系统专业的必修课之一,是一门综合性的专业基础课。
本课程较系统地介绍了软件设计中常用的数据结构以及相应的实现算法,如线性表、栈、队列、树和二叉树,图、检索和排序等,并对性能进行分析和比较,内容非常丰富。
本课程设计我们要解决的问题是图最小生成树问题。
要用到图的先相关数据结构和求最小生成树的两种数据结构算法普里姆算法和克鲁斯卡尔算法,以及储存图的边和点的邻接矩阵。
数据结构最小生成树
p= new CSNode(v);
if(first){
V
T.lchild=p;first=false;
}
else{ q.nextsibling=p;} w1
w2
w3
q=p;
DFSTree(G,w.q); }
SG1
SG2
SG3
}
生成森林
一、定义 非连通图G的每个连通分量的生成树,
构成了图G的生成森林
生成森林
非连通图G:
0
1
a
b
2 3 45
cd
ef
7h
k8
G的深度优先搜索生 成森林:
ab
6 g
cg
h
df
k e
生成森林算法
void DFSForest(Graph G, CSNode T){ T=null; for(v=0;v=G.vexnum;++v)
v.visit=false; for(v=0;v=G.vexnum;++v)
4
13
10
v1
2
v2
1
v3
2
v4
7
v5
v3
2
v4
v5
58
4
1
v7
Kruskal算法
算法描述:
构造非连通图 ST=(V,{ }); k=i=0; // k 选中的边数 while (k<n-1) { ++i; 检查边集E中第i条权值最小的边(u,v); if 若(u,v)加入ST后不使ST中产生回路, 则输出边(u,v); 且k++;
生成树算法
void DFSTree(Graph G,int v,CSNode T){ 算法以孩子
数据结构 实验8 最小生成树
(1)复习图的存储方法和图的遍历方法;
(2)进一步掌握图的非线性特点、递归特点和动态特性;
(3)掌握最小生成树的求解算法。
2、实验内容
(1)用Prim算法求最小生成树;
(2)输入网的二维矩阵,输出最小生成树;
3、实验要求
(1)分析算法思想,利用C(C++)语言完成程序设计。
(2)上机调试通过实验程序。
if(g[k][j]<lowcost[j])
{lowcost[j]=g[k][j];
closest[j]=k;
}
printf("\n");
}
}
int adjg(int g[][max]) //建立无向图
{
int n,e,i,j,k,v1,v2,weight;
printf("输入顶点个数,边的条数:");
⑵源代码
#include <stdio.h>
#define inf 9999
#define max 40
void prim(int g[][max],int n) // prim的函数
{
int lowcost[max],closest[max];
int i,j,k,min;
for(i=2;i<=n;i++) // n个顶点,n-1条边
scanf("%d,%d",&n,&e);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
g[i][j]=inf; //初始化矩阵,全部元素设为无穷大
for(k=1;k<=e;k++)
最小生成树和最短路径数据结构实验
实验报告六月 18 2015姓名:陈斌学号:E 专业:13计算机科学与技术数据结构第八次实验学号E专业计算机科学与技术姓名陈斌实验日期教师签字成绩实验报告【实验名称】最小生成树和最短路径【实验目的】(1)掌握最小生成树以及最短路径的相关概念;(2)掌握Prim算法和Kruskal算法;(3)掌握Dijkstra算法【实验内容】采用普里姆算法求最小生成树(1)编写一个算法,对于教材图(a)所示的无向带权图G采用普里姆算法输出从顶点V1出发的最小生成树。
图的存储结构自选。
(2)对于上图,采用克鲁斯卡尔算法输出该图的最小生成树。
(提示:a.先对边按权值从小到大排序,得有序边集E;为所有顶点辅设一个数组Vset,标记各顶点所处的连通分量,初始时各不相同。
b. 依次从E中取出一条边(i,j),检查顶点i和j是否属于同一连通分量,如是,则重取下一条边;否则,该边即为生成树的一条边,输出该边,同时将所有与j处于同一连通分量的顶点的Vset 值都修改为与i的相同。
c.重复b步直至输出n-1条边。
)源代码::#include<>#include<>#include<> dj=INFINITY; /* 网 */}printf("请输入%d条边的顶点1 顶点2 权值(用空格隔开): \n",; for(k=0;k<;++k){scanf("%s%s%d%*c",va,vb,&w); /* %*c吃掉回车符 */i=LocateVex(G,va);j=LocateVex(G,vb);[i][j].adj=[j][i].adj=w; /* 无向 */}=AN;return OK;}typedef struct{ /* 记录从顶点集U到V-U的代价最小的边的辅助数组定义 */VertexType adjvex;VRType lowcost;}minside[MAX_VERTEX_NUM];int minimum(minside SZ,MGraph G){ /* 求的最小正值 */int i=0,j,k,min;while(!SZ[i].lowcost)i++;min=SZ[i].lowcost; /* 第一个不为0的值 */k=i;for(j=i+1;j<;j++)if(SZ[j].lowcost>0)if(min>SZ[j].lowcost){min=SZ[j].lowcost;k=j;}return k;}void MiniSpanTree_PRIM(MGraph G,VertexType u){ /* 用普里姆算法从第u个顶点出发构造网G的最小生成树T,输出T的各条边算法 */int i,j,k;minside closedge;k=LocateVex(G,u);for(j=0;j<;++j) /* 辅助数组初始化 */{if(j!=k){strcpy(closedge[j].adjvex,u);closedge[j].lowcost=[k][j].adj;}}closedge[k].lowcost=0; /* 初始,U={u} */printf("最小代价生成树的各条边为:\n");for(i=1;i<;++i){ /* 选择其余个顶点 */k=minimum(closedge,G); /* 求出T的下一个结点:第K顶点 */printf("(%s-%s)\n",closedge[k].adjvex,[k]); /* 输出生成树的边 */ closedge[k].lowcost=0; /* 第K顶点并入U集 */for(j=0;j<;++j)if[k][j].adj<closedge[j].lowcost){ /* 新顶点并入U集后重新选择最小边 */strcpy(closedge[j].adjvex,[k]);closedge[j].lowcost=[k][j].adj;}}}typedef struct node{int va; <a[j+1].w) { dj!=INFINITY){E[k].va=i;E[k].vb=j;E[k].w=[i][j].adj;k++;}}}Heapsort(E,G);Initialize(G); a];int sn2=Vset[E[j].vb];a],[E[j].vb],E[j].w);k++;for (i=0;i<;i++)if (Vset[i]==sn2)Vset[i]=sn1;}j++;}}void main(){MGraph G;CreateAN(G);cout<<"--------普里姆算法输出从顶点V1出发的最小生成树--------\n"<<endl;MiniSpanTree_PRIM(G,[0]);cout<<"------------------------------------------------------\n"<<endl;cout<<"--------克鲁斯卡尔算法输出从顶点V1出发的最小生成树----\n"<<endl;MiniSpanTree_Kruskal(G);cout<<"------------------------------------------------------"<<endl;}运行结果:采用迪杰斯特拉算法求单源最短路径编写一个算法,采用迪杰斯特拉算法,输出如下图所示的有向带权图G 中从顶点a到其他各顶点的最短路径长度和最短路径。
数据结构实验报告-最小生成树(精选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算法求解最小生成树。
Kruskal算法基于一个贪心的思想:每次选择权值最小的边,直到生成树中包含所有的节点。
具体算法如下:1.根据给定的连通图构造一个边的集合E,E中包含图中所有的边。
2.将E中的边按照权值从小到大排序。
3.依次遍历排序后的边,如果该边的两个节点不在同一个连通分量中,则选择该边,并将这两个节点合并到一个连通分量中。
4.重复第3步,直到生成树中包含所有的节点。
实验步骤及结果:1.根据给定的连通图构造边的集合E,并将E中的边按照权值从小到大排序。
2.初始化一个空的集合T作为最小生成树的边集合。
3.依次遍历排序后的边,如果该边的两个节点不在同一个连通分量中,则选择该边,并将这两个节点合并到一个连通分量中,同时将该边添加到集合T中。
4.重复第3步,直到生成树中包含所有的节点。
实验结果分析:通过Kruskal算法,可以得到带权无向连通图的最小生成树。
最小生成树具有多个优点,如能够保证连通、权值最小、无回路。
在实际应用中,最小生成树常常用于网络设计、集成电路布线等领域。
实验总结:通过本次实验,我掌握了最小生成树的概念和Kruskal算法的原理和实现方法。
实验中,我通过定义边的数据结构和构造边的集合,实现了Kruskal算法求解最小生成树。
通过实验,我深刻认识到数据结构在解决实际问题中的重要性和实用性。
最小生成树作为一种常用的图论算法,在实际应用中具有广泛的应用和重要的价值。
掌握了最小生成树的概念和算法,我相信能够在今后的学习和工作中更好地应用数据结构算法解决实际问题。
数据结构最小生成树
数据结构最小生成树
在图论中,最小生成树指的是在一个连通无向图中,由所有的节
点以最小的权值得到的一棵生成树。
在这个生成树中,边的总权值是
所有可能的生成树中最小的。
最小生成树的算法旨在找到这样一棵生
成树,同时保证该生成树的节点均可以相互到达,使得图中的所有节
点都能够相互连通。
最常用的算法是Prim算法和Kruskal算法。
Prim算法以某个节点为起点开始构建,每次选择与当前生成树相邻且权值最小的边进行扩展,逐步构建出最小生成树。
而Kruskal算法则是将所有边进行排序,依次加入生成树中,直至生成树覆盖了所有的节点。
这两种算法都可
以保证最终得到的生成树是最小的。
最小生成树的应用非常广泛,在许多网络设计、通信、交通等领
域都是至关重要的。
例如,在城市规划中,最小生成树可以帮助我们
设计出最经济、最便捷的交通路线;在通信网络中,最小生成树可以
帮助我们构建具有最小延迟和最大数据传输速度的网络,提高通信质量。
此外,最小生成树也是许多其他算法的基础,如图的遍历、网络
流等。
总的来说,最小生成树是一种非常重要的数据结构,解决了许多
实际问题,也为高级算法的开发提供了很好的基础。
在实际应用中,
我们需要根据具体情况选用不同的算法,并对算法的性能和效率进行
评估。
只有充分理解最小生成树算法的原理,才能够更好地解决实际问题,提高工作效率。
数据结构实验最小生成树
数据结构实验最小生成树数据结构实验报告最小生成树问题一、问题描述:若要在n个城市之间建设通信网络,只需要架设n-1条线路即可。
如何以最低的经济代价建设这个通信网,是一个网的最小生成树问题基本要求(1)从文件中读入图的信息。
(2)利用克鲁斯卡尔算法求网的最小生成树。
(3)以文本形式生成树中各条边以及他们的权值。
二(需求分析:1、需定义结构体数组,根据权值逐一选择边。
三(概要设计抽象数据类型:需定义结构体数组,存储每条边的起点,终点,权值。
算法的基本思想:1、图的信息的读取:定义结构体数组,存储每条边的起点,终点,权值。
2、对每条边在数组中的位置处理:选边需从最小的开始,故按边的权值从小到大进行排序。
3、边的选取: 从最小的边的开始,若边的两端点不属于同一集合,则选取该边。
并将该边的两个顶点所在的两个集合合并成为一个。
因为有n个顶点,故只需选取n-1条边。
程序的流程:(1) 输入模块: 读入图的信息(顶点和边,用结构体数组进行存储)。
(2) 处理模块:Kruskal算法。
(3) 输出模块:将结果输出。
四(详细设计:算法的具体步骤:struct G{int fromvex;int endvex;int weight;}GE[100],cur[100];void swap(G* GE,int i,int j){ //交换函数int temp=GE[i].fromvex;GE[i].fromvex=GE[j].fromvex;GE[j].fromvex=temp;temp=GE[i].endvex;GE[i].endvex=GE[j].endvex;GE[j].endvex=temp;temp=GE[i].weight;GE[i].weight=GE[j].weight;GE[j].weight=temp;}void Kruskal(int n){int i,j,k=0,pos=-1,m1,m2;bool** s=new bool *[n];//定义一个二维数组,用来判断是否为同一类for(i=0;i<n;i++)s[i]=new bool[n];for(i=0;i<n;i++){for(j=0;j<n;j++){if(i==j)s[i][j]=true; //初始化数组elses[i][j]=false;}}while(k<n-1){for(i=0;i<n;i++){if(s[i][GE[k].fromvex]==1)m1=i;if(s[i][GE[k].endvex]==1)m2=i;}if(m1!=m2){//判断是否为同一类,如果为同一类(该类中所有的点到起点和终//点的边在s 数组中赋为1),cur[++pos].fromvex=GE[k].fromvex;cur[pos].endvex=GE[k].endvex;cur[pos].weight=GE[k].weight;for(i=0;i<n;i++){if(s[m1][i] || s[m2][i])//把该点添加到该类,并和并两个类s[m1][i]=1;elses[m1][i]=0;s[m2][i]=0;}}k++;}for(i=0;i<n;i++){delete []s[i];}}int main(){int i,j;int numVertex,numEdge;cout<<"请输入点的个数和边的条数:"<<endl; cin>>numVertex>>numEdge;cout<<"请输入边的起始位置和边的权值:"<<endl;for(i=0;i<numEdge;i++)cin>>GE[i].fromvex>>GE[i].endvex>>GE[i].weight;for(i=0;i<numEdge;i++)for(j=i;j<numEdge;j++){if(GE[j].weight<GE[i].weight)//将边的权值按从小到大排列swap(GE,i,j);}Kruskal(numEdge);for(i=0;i<numVertex-1;i++) cout<<cur[i].fromvex<<"->"<<cur[i].endvex<<":"<<cur[i].weight<<endl;system("pause");return 0;}五(调试分析:将选边的过程输出来检验算法的正确性。
实验八 图的最小生成树
浙江大学城市学院实验报告课程名称数据结构与算法实验项目名称实验八图的最小生成树实验成绩指导老师(签名)日期一. 实验目的和要求1.掌握图的最小生成树的概念。
2.掌握生成最小生成树的Prim算法(用邻接矩阵表示图)。
二. 实验内容1、编写用邻接矩阵表示无向带权图时图的基本操作的实现函数,主要包括:①初始化邻接矩阵表示的无向带权图void InitMatrix(adjmatrix G); ②建立邻接矩阵表示的无向带权图void CreateMatrix(adjmatrix G, int n)(即通过输入图的每条边建立图的邻接矩阵); ③输出邻接矩阵表示的无向带权图void PrintMatrix(adjmatrix G, int n) (即输出图的每条边)。
把邻接矩阵的结构定义以及这些基本操作实现函数存放在头文件Graph1.h中。
2、编写生成最小生成树的Prim算法函数void Prim(adjmatrix G, edgset CT,int n)以及输出边集数组的函数void PrintEdge(edgeset CT, int n)。
3、编写测试程序(即主函数),通过调用上述函数首先建立并输出无向带权图,然后生成最小生成树并输出(即输出边集)。
要求:把边集数组的结构定义、Prim算法函数、输出边集数组的函数PrintEdge 以及主函数存放在文件test8.cpp中。
测试数据如下:4、填写实验报告,实验报告文件取名为report8.doc。
5、上传实验报告文件report8.doc与源程序文件test8.cpp及Graph1.h到Ftp 服务器上自己的文件夹下。
三.函数的功能说明及算法思路函数:void InitMatrix(adjmatrix GA)功能:初始化邻接矩阵表示的无向带权图函数:void CreateMatrix(adjmatrix GA,int n)功能:建立邻接矩阵表示的无向带权图函数:void PrintMatrix(adjmatrix GA,int n)功能:输出邻接矩阵表示的无向带权图函数:void Prim(adjmatrix GA,edgeset CT,int n)功能:生成最小生成树思路:设从连通带权图G = { V, E }中的某一顶点u0 出发;选择与它关联的具有最小权值的边<u0, v>,将其顶点加入到生成树的顶点集合U中;以后每一步从一个顶点在U中,而另一个顶点在V-U中的各条边中选择权值最小的边<u, v>,把该顶点加入到集合U中;如此继续下去,直到图中的所有顶点都加入到生成树顶点集合U中为止。
数据结构(最小生成树)
设置一个辅助数组closedge,来记录 从顶点集U到V-U具有最小代价的边。
struct { VertexType adjvex; // U集中的顶点序号 VRType lowcost; // 边的权值
} closedge[MAX_VERTEX_NUM];
A
6
5
B5
1
D
5CΒιβλιοθήκη 3642E6
F
Prim算法
例如:
a 19
b5
14 12
18
7
c
16 e 8
3
g
d
27
21
f
例如:
a
19
b
14 12
18
7
16 e 8
5
c
3
g
d
27
21
f
克鲁斯卡尔算法
TE
AC
A
6
5
1
B5
1
D
DF
5
C
36
4
2
2 BE
E6
F
3
CF
4
BC
5
算法分析:
• 克鲁斯卡尔算法的时间复杂度为O(eloge)。
• 该算法与网中的边的数目有关。 • 适用于求边稀疏的网的最小生成树。
有最小权值(代价)的边,其中u∈U, v ∈V-U,则最小生成树中必包含边
(u,v)。
u
v
U V-U
构造最小生成树的算法
算法一:(普里姆算法) 算法二:(克鲁斯卡尔算法)
普里姆算法的基本思想:
• 假设N=(V,{E})是连通图,TE是N上最小生成树中
边的集合。算法从U={u0}(u0∈V),TE={}开始, 重复执行下述操作:在所有u∈U, v ∈V-U的边 (u,v)∈E中找一条代价最小的边(u0,v0)并入集合TE,
数据结构-最小生成树实验报告
#include<stdio.h>#include<stdlib.h>#define MAXLEAF 100#define INF 100000#define EDGENUMBER MAXLEAF*MAXLEAF/2typedef int EdgeType;typedef int VertexType;typedef struct{EdgeType val[MAXLEAF][MAXLEAF];VertexType ves[MAXLEAF];int v;int e;}MGraph;typedef struct{int vex1,vex2;int w;}kedge;void creat_MGraph(MGraph *M){int i,j,k;int w;printf("请输入图的顶点个数及边数:\n");scanf("%d%d",&(M->v),&(M->e));printf("请依次填充顶点信息:\n");for(i=0;i<M->v;i++)scanf("%d",&(M->ves[i]));for(i=0;i<M->v;i++)for(j=0;j<M->v;j++)if(i==j) M->val[i][j]=0;else M->val[i][j]=INF;printf("请依次输入图的边两个顶点顶点的权值:(格式:a b c)\n");for(k=0;k<M->e;k++){scanf("%d%d%d",&i,&j,&w);M->val[i-1][j-1]=w;M->val[j-1][i-1]=w;}}VertexType kruskal(MGraph M){int tag[MAXLEAF];kedge Ke[EDGENUMBER];int i,j;VertexType length=0;int n=0;for(i=0;i<M.v;i++) tag[i]=i;for(i=0;i<M.v;i++)for(j=i+1;j<M.v;j++)if(M.val[i][j]!=INF){Ke[n].vex1=i;Ke[n].vex2=j;Ke[n++].w=M.val[i][j];}kedge temp;for(i=0;i<n-1;i++)for(j=0;j<n-i-1;j++)if(Ke[j].w>Ke[j+1].w){temp=Ke[j+1];Ke[j+1]=Ke[j];Ke[j]=temp;}for(i=0;i<n;i++){int first,second;first = tag[Ke[i].vex1];second = tag[Ke[i].vex2];if(first!=second){length+=Ke[i].w;printf("%d->%d: %d\n",Ke[i].vex1,Ke[i].vex2,Ke[i].w);tag[Ke[i].vex2]=first;for(j=0;j<M.v;j++){if(second==tag[j])tag[j]=first;}}}return length;}int main(){MGraph M;int len;creat_MGraph(&M);printf("最小生成树:\n");len=kruskal(M);printf("最小成本:%d",len);return 0;}。
最小生成树实验报告
最小生成树实验报告最小生成树(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从实验结果来看,无论是规模较小的图还是规模较大的图,我们都能够得到最小生成树,并且所得到的结果是正确的。
数据结构实验报告最小生成树参考模板
HUNAN UNIVERSITY 课程实习报告
题目:最小生成树
学生姓名:
学生学号:
专业班级:
指导老师:
完成日期:
一、需求分析
若要在n个城市之间建设通信网络,只需要架设n-1条线路即可。
如何以最低的经济代价建设这个通信网,是一个网的最小生成树问题
二、概要设计
抽象数据类型
用数组将边的距离及权值进行存储并排序。
算法的基本思想
构造生成树的网一定是无向网。
并设顶点数不超过30个,边权值为小于100的整数。
根据克鲁斯卡尔算法的特点,为便于选择选择权值小的边,存储结构不选用邻接矩阵和邻接表,而是可以用存储边(带权)的数组表示图。
程序的流程
程序由三个模块构成:
(1)从文件中读入图的信息。
(2)利用克鲁斯卡尔算法求网的最小生成树。
(3)以文本形式生成树中各条边以及他们的权值。
三、
四、详细设计
算法的具体步骤
先将用户的输入的顶点和边的数量,根据这些信息构建出图的结构,最后对边的权值进行排序。
输入和输出的格式
输入:
输入顶点和边的个数及顶点之间的权值。
输出:
输出最小生成树的序列。
五、测试结果
六、实验心得
实验的时候不是这个结果啊,可能是哪个环节出了错误,但是思想没有问题的,通过本次实验学会了用C++实现最小生成树。
友情提示:范文可能无法思考和涵盖全面,供参考!最好找专业人士起草或审核后使用,感谢您的下载!。
数据结构最小生成树实验报告
实验报告课程名:数据结构(C语言版) 实验名:最小生成树姓名:班级:学号:时间:2014.11.26一实验目的与要求1. 掌握生成最小生成树的算法2. 利用C 语言实现Prim 算法或者Kruskal 算法二实验内容•将一个图存储起来•求取该图的最小生成树三实验结果与分析程序:#include <stdio.h>#include <stdlib.h>#define MAX 100#define MAXCOST 0x7fffffffint graph[MAX][MAX];int Prim(int graph[][MAX], int n){/* lowcost[i]记录以i为终点的边的最小权值,当lowcost[i]=0时表示终点i加入生成树 */int lowcost[MAX];/* mst[i]记录对应lowcost[i]的起点,当mst[i]=0时表示起点i加入生成树 */int mst[MAX];int i, j, min, minid, sum = 0;/* 默认选择1号节点加入生成树,从2号节点开始初始化 */for (i = 2; i <= n; i++){/* 最短距离初始化为其他节点到1号节点的距离 */lowcost[i] = graph[1][i];/* 标记所有节点的起点皆为默认的1号节点 */mst[i] = 1;}/* 标记1号节点加入生成树 */mst[1] = 0;/* n个节点至少需要n-1条边构成最小生成树 */for (i = 2; i <= n; i++){min = MAXCOST;minid = 0;/* 找满足条件的最小权值边的节点minid */for (j = 2; j <= n; j++){/* 边权值较小且不在生成树中 */if (lowcost[j] < min && lowcost[j] != 0){min = lowcost[j];minid = j;}}/* 输出生成树边的信息:起点,终点,权值 */printf("%c - %c : %d\n", mst[minid] + 'A' - 1, minid + 'A' - 1, min);/* 累加权值 */sum += min;/* 标记节点minid加入生成树 */lowcost[minid] = 0;/* 更新当前节点minid到其他节点的权值 */for (j = 2; j <= n; j++){/* 发现更小的权值 */if (graph[minid][j] < lowcost[j]){/* 更新权值信息 */lowcost[j] = graph[minid][j];/* 更新最小权值边的起点 */mst[j] = minid;}}}/* 返回最小权值和 */return sum;}int main(){int i, j, k, m, n;int x, y, cost;char chx, chy;/* 读取节点和边的数目 */scanf("%d%d", &m, &n);getchar();/* 初始化图,所有节点间距离为无穷大 */for (i = 1; i <= m; i++){for (j = 1; j <= m; j++){graph[i][j] = MAXCOST;}}/* 读取边信息 */for (k = 0; k < n; k++){scanf("%c %c %d", &chx, &chy, &cost);getchar();i = chx - 'A' + 1;j = chy - 'A' + 1;graph[i][j] = cost;graph[j][i] = cost;}/* 求解最小生成树 */cost = Prim(graph, m);/* 输出最小权值和 */printf("Total:%d\n", cost);//system("pause");return 0;}运行结果:图1.最小生成树运行结果。
最小生成树实验报告
北京理工大学软件学院一、实验目的1. 通过上机程序,进一步加深对最小生成树的理解。
2. 掌握Kruskal算法。
3. 学会用程序解决离散数学中的问题。
4. 增强我们编写程序的能力。
二、实验内容求带权无向联通平面图的最小生成树三、实验环境我的实验依旧是在VC6.0实验环境下完成的,而所设计的程序也在这个环境下通过了编译,运行和测试。
四、实验原理和实现过程利用Kruskal算法求最小生成树,原理如下:1.选取最小权边e1,置边数j←1.2.i=n-1结束,否则转c。
3.设已经选择的边为e1,e2,……,ei,在G中选取不同于e1,e2,……ei的边,使{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 if10.end while五、实验源代码及分析#include<stdio.h>struct Edge{int from, to, weight; //定义一个数据结构,存放点和边的关系以及边的权值};Edge edge[100], temp; //用定义的数据结构来定义一个数组和一个变量int i, j, n, m;int p[100];int seek(int x) //用来找出当前端点所在集合编号{if(p[x]==x)return x;elsereturn p[x]=seek(p[x]);}Int Kruskal(){int x, y,k=0;for(i=0;i<100;i++)p[i]=i;for(i=0;i<m;i++){x=seek(edge[k].from); //找出当前边两个端点所在集合编号y=seek(edge[k].to);if(x!=y) //如果在不同集合,合并{printf("(%d, %d): %d\n",edge[k].from, edge[k].to, edge[k].weight); //输出这时的边的端点和权值p[x]=y;}k++;}return 0;}int main(){printf("Please input the number of the nodes and edges:\n");scanf("%d%d",&n,&m); //输入有n个节点m条边printf("Please input the edges and its weight:\n");for(i=0;i<m;i++){scanf("%d%d%d",&edge[i].from, &edge[i].to, &edge[i].weight); //输入每一条边的起点、终点和权值}for(i=0;i<m-1;i++) //对边的权值进行从小到大的排列for(j=i+1;j<m;j++)if(edge[i].weight>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、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
g[v2][v1]=weight;
}
return(n);
}
void prg(int g[][max],int n) //输出无向图的邻接矩阵
{
int i,j;
for(i=0;i<=n;i++)
printf("%d\t",i);
for(i=1;i<=n;i++)
{
printf("\n%d\t",i);
scanf("%d,%d",&n,&e);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
g[i][j]=inf; //初始化矩阵,全部元素设为无穷大
for(k=1;k<=e;k++)
{
printf("输入第%d条边的起点,终点,权值:",k);
scanf("%d,%d,%d",&v1,&v2,&weight);
1、实验目的
(1)复习图的存储方法和图的遍历方法;
(2)进一步掌握图的非线性特点、递归特点和动态特性;
(3)掌握最小生成树的求解算法。
2、实验内容
(1)用Prim算法求最小生成树;
(2)输入网的二维矩阵,输出最小生成树;
3、实验要求
(1)分析算法思想,利用C(C++)语言完成程序设计。
(2)上机调试通过实验程序。
if((lowcost[j]<min)&&(lowcost[j]!=0))
{
min=lowcost[j];
k=j;
}
printf("(%d,%d)%d\t",closest[k],k,min);
lowcost[k]=0; //顶点k加入U
for(j=2;j<=n;j++) //修改由顶点k到其他顶点边的权值
⑵源代码
#include <stdio.h>
#define inf 9999
#define max 40
void prim(int g[][max],int n) // prim的函数
{
int lowcost[max],closest[max];
int i,j,k,min;
for(i=2;i<=n;i++) // n个顶点,n-1条边
for(j=1;j<=n;j++)
printf((g[i][j]==inf)?"\t":"%d\t",g[i][j]);
}
printf("\n");
}
void mainn;
n=adjg(g);
printf("输入无向图的邻接矩阵:\n");
prg(g,n);
printf("最小生成树的构造:\n");
(3)输入数据,并求最小生成树。
(4)给出具体的算法分析,包括时间复杂度和空间复杂度等。
(5)撰写实验报告(把输入实验数据及运行结果用抓图的形式粘贴到实验报告上)。
4、实验步骤与源程序
⑴实验步骤
我先从具体的问题中抽象出适当的数学模型,然后设计出相应的算法,其中,需要首先使用prim的函数将矩阵初始化,然后输出无向图的邻接矩阵,再求最小生成树的求解算法,最后,编写主函数,串接程序,并调试程序,得出实验结果。
if(g[k][j]<lowcost[j])
{lowcost[j]=g[k][j];
closest[j]=k;
}
printf("\n");
}
}
int adjg(int g[][max]) //建立无向图
{
int n,e,i,j,k,v1,v2,weight;
printf("输入顶点个数,边的条数:");
prim(g,n);
}
5、测试数据与实验结果(可以抓图粘贴)
6、结果分析与实验体会
本次实验是参考了范例程序,经过自己的改写,从而实现要求。先做简单的输出,一步步的再做其它格式的设置。这次的实验我们要做的是图的存储方法和图的遍历方法,要求我们掌握的是非线性特点,递归特点和动态特征,最小生成树的求解等。首先将初始化矩阵,全部元素设为无穷大,使用的是prim的函数,输出无向图的邻接矩阵。在做这次实验之前先参考了一个例子,在结合书本的要求编写程序,在调试程序的过程中,遇到很多问题,但是最终还是得以解决。
{lowcost[i]=g[1][i]; //初始化
closest[i]=1; //顶点未加入到最小生成树中
}
lowcost[1]=0; //标志顶点1加入U集合
for(i=2;i<=n;i++) //形成n-1条边的生成树
{
min=inf;
k=0;
for(j=2;j<=n;j++) //寻找满足边的一个顶点在U,另一个顶点在V的最小边