求最小生成树(Kruskal算法)实验报告

合集下载

最小生成树 实验报告

最小生成树 实验报告

最小生成树实验报告最小生成树实验报告一、引言最小生成树是图论中的一个重要概念,它在实际问题中有着广泛的应用。

本次实验旨在通过编程实现最小生成树算法,并通过实验数据对算法进行分析和评估。

二、算法介绍最小生成树算法的目标是在给定的带权无向图中找到一棵生成树,使得树上所有边的权重之和最小。

本次实验我们选择了两种经典的最小生成树算法: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)一、引言《数据结构》是计算机科学与技术专业和信息管理与信息系统专业的必修课之一,是一门综合性的专业基础课。

本课程较系统地介绍了软件设计中常用的数据结构以及相应的实现算法,如线性表、栈、队列、树和二叉树,图、检索和排序等,并对性能进行分析和比较,内容非常丰富。

本课程设计我们要解决的问题是图最小生成树问题。

要用到图的先相关数据结构和求最小生成树的两种数据结构算法普里姆算法和克鲁斯卡尔算法,以及储存图的边和点的邻接矩阵。

数据结构-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算法基本思路是:假设每个点都有一对标号 (d j, p j),其中d j是从起源点s到点j的最短路径的长度 (从顶点到其本身的最短路径是零路(没有弧的路),其长度等于零);p j则是从s到j的最短路径中j点的前一点。

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

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

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

3) 选取下一个点。

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

4) 找到点i的前一点。

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

实验5最小生成树算法的设计与实现(报告)

实验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户人家,每家都养了一条狗,有一天他们接到通知说院子里有狗生病了,并要求所有主人在发现自己家狗生病的当天就要把狗枪杀掉。

最小生成树Kruskal算法报告

最小生成树Kruskal算法报告

最小生成树Kruskal算法报告沈阳航空航天大学课程设计报告课程设计名称:数据结构课程设计课程设计题目:最小生成树Kruskal算法院(系):计算机学院专业:计算机科学与技术目录1 课程设计介绍 (1)1.1课程设计内容 (1)1.2课程设计要求 (1)2 课程设计原理 (2)2.1课设题目粗略分析 (2)2.2原理图介绍 (3)2.2.1 功能模块图 (3)2.2.2 流程图分析 (4)3 数据结构分析 (10)3.1存储结构 (10)3.2算法描述 (10)4 调试与分析 (13)4.1调试过程 (13)4.2程序执行过程 (13)参考文献 (16)附录(关键部分程序清单) (17)1 课程设计介绍1.1 课程设计内容设计程序,编写算法能建立带权图,并能够用Kruskal算法求该图的最小生成树,系统主要功能如下:1.最小生成树能够选择图上的任意一顶点做根结点;2.最小生成树输出不必采用图形方式,可按父结点和子女结点集的形式输出。

1.2 课程设计要求1.顶点信息用字符串,数据可自行设定;2.参考相应的资料,独立完成课程设计任务;3.交规范课程设计报告和软件代码。

2 课程设计原理2.1 课设题目粗略分析根据课设题目要求,拟将整体程序分为五大模块。

此五个模块相互联系,有嵌套调用的情况,以下是五个模块的大体分析:1.创建模块,建立无向连通图,创建图的总信息;2.发现模块,用Kruscal算法求最小生成树并调用search()函数;3.寻找模块,找出最小边(路径),使各连通分量相统一,输出最小生成树对应边及对应结点并调用change()函数;4.改变模块,改变两个结点间的权值,使下一次寻找时不至于重复;5.选择模块,选择最小生成树的根结点并按父亲节点和子女结点的形式输出最小生成树。

2.2 原理图介绍2.2.1功能模块图图2.1功能模块图2.2.2 流程图分析1.创建模块,建立无向连通图,创建图的总信息,流程图如下:图2.2创建块流程图2.发现模块,用Kruscal算法求最小生成树并调用search()函数,流程图如下:图2.3发现模块流程图3.寻找模块,找出最小边(路径),使各连通分量相统一,输出最小生成树对应边及对应结点并调用change()函数,具体流程图如下:图2.4寻找模块流程图图2.5寻找模块流程图4.改变模块,改变两个结点间的权值,使下一次寻找时不至于重复,具体流程图如下:图2.6改变模块流程图5.选择模块,选择最小生成树的根结点并按父亲节点和子女结点的形式输出最小生成树法,具体流程图如下:图2.7选择模块流程图3 数据结构分析3.1 存储结构定义结构体数组建立整个图的信息,包括图的各个结点的名称及对应的数字编号,连接两结点的边的权值,建立存在互相连通的两结点之间的联系且采用从头插入的链表连接方式,并且每个结点建立对应的邻接表,都采用头插入的方式,相互连接的两结点都存有对应的边的权值,存储代码如下:typedef struct link{int connect;//结点编号int fee;//权值struct link *next;}edgenode;typedef struct node{char name[10];//结点名称edgenode *link;}jiedian;typedef struct{jiedian vex[MAXSIZE];int jiedian_n,jiedian_e;//结点个数,边数(路径数)}jiedian_graph;3.2 算法描述1.建立两结点间联系,采用从头插入的方式,其中p,q分别为两项链结点的编号,简单算法说明如下:p->next=ga->vex[a].link;//建立两个结点间的联系ga->vex[a].link=p;q->next=ga->vex[b].link;ga->vex[b].link=q;2.寻找所建图中最小权值所在边对应的两个结点,如果寻找过则重新标记为一个统一的更大权值,以防止下次寻找时影响寻找的结果,简单算法说明如下:for(j=1;jjiedian_n+1;j++)//找权值最少的两个结点{p=ga->vex[j].link;//记下当前结点,以便在此结点的联系链中找到此链下的最小权值边(路径) while(p!=NULL){if((p->fee<min)&&(p->fee!=100))</min)&&(p->{min=p->fee;min_sign=p->connect;min_record=j;}p=p->next;}}3. 修改找到最小权值的边的权值,使其赋予更大的权值,简单算法说明如下:while(p!=NULL){if(p->connect==min_b)p->fee=100;q=p;p=p->next;}4.输出结点所连接的各个结点的的名称,运用啦信息表建立的头插入方式的邻接表,简单算法说明如下:while(p!=NULL){if(Mother[p->connect]!=0){printf("%s ",ga->vex[p->connect].name);Mother[p->connect]=0;}p=p->next;}4 调试与分析4.1 调试过程在调试程序是主要遇到一下几类问题:1.邻接表的建立采用了头插入的方式,对应结点的插入顺序不应错误。

数据结构实验报告-最小生成树(精选5篇)

数据结构实验报告-最小生成树(精选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算法课程名称:离散数学实验类型:□演示性□验证性□操作性■设计性□综合性专业:软件工程班级: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初始化,从而是的程序能正常运行。

生成树实验报告

生成树实验报告

一、实验目的1. 理解生成树的概念和作用;2. 掌握Prim算法和Kruskal算法实现生成树的方法;3. 分析算法的时间复杂度和空间复杂度;4. 提高算法设计与分析能力。

二、实验原理生成树(Spanning Tree)是一个无向图的所有顶点构成的一棵树,且该树包含了原图的所有顶点。

生成树在计算机网络、电路设计等领域具有广泛的应用。

在无向图中,如果任意两个顶点之间都存在路径,则称该图是连通的。

对于连通图,一定存在一棵生成树。

Prim算法和Kruskal算法是两种常见的生成树算法,它们分别采用贪心策略和最小生成树算法实现。

三、实验内容1. Prim算法实现生成树(1)初始化:设置一个数组来记录每个顶点与当前生成树的连接情况,以及一个数组来记录每个顶点到生成树的距离。

(2)选择一个顶点作为起始顶点,将其距离设置为0,其他顶点距离设置为无穷大。

(3)在当前生成树上选择距离最小的顶点,将其加入生成树,并将该顶点与其他顶点的距离更新。

(4)重复步骤(3),直到所有顶点都被加入生成树。

2. Kruskal算法实现生成树(1)将所有边按照权值从小到大排序。

(2)创建一个并查集,用于判断两个顶点是否属于同一个集合。

(3)遍历排序后的边,对于每条边,判断其两个顶点是否属于同一个集合:(a)如果属于同一个集合,则跳过该边;(b)如果不属于同一个集合,则将这条边加入生成树,并将两个顶点所属的集合合并。

(4)重复步骤(3),直到生成树包含所有顶点。

四、实验步骤1. 创建一个无向图,包含若干顶点和边。

2. 使用Prim算法实现生成树,记录算法运行时间。

3. 使用Kruskal算法实现生成树,记录算法运行时间。

4. 分析两种算法的时间复杂度和空间复杂度。

五、实验结果与分析1. Prim算法实现生成树(1)顶点集合:V = {A, B, C, D, E, F}(2)边集合:E = {(A, B, 1), (A, C, 3), (A, D, 2), (B, C, 2), (B, D, 2), (C, D, 1), (C, E, 4), (D, E, 3), (D, F, 2), (E, F, 1)}(3)Prim算法运行时间:0.001秒2. Kruskal算法实现生成树(1)顶点集合:V = {A, B, C, D, E, F}(2)边集合:E = {(A, B, 1), (A, C, 3), (A, D, 2), (B, C, 2), (B, D, 2), (C, D, 1), (C, E, 4), (D, E, 3), (D, F, 2), (E, F, 1)}(3)Kruskal算法运行时间:0.001秒通过实验,我们可以得出以下结论:1. Prim算法和Kruskal算法均可以有效地实现生成树,且在时间复杂度和空间复杂度上表现良好。

数据结构实验报告最小生成树

数据结构实验报告最小生成树

数据结构实验报告最小生成树实验目的:掌握最小生成树的概念和算法,培养分析和解决实际问题的能力。

实验内容:利用Kruskal算法求解带权无向连通图的最小生成树。

实验原理:最小生成树是指一个连通图的生成树,其中所有边的权值和最小。

最小生成树问题在图论中有着重要的应用,如网络设计、集成电路布线等领域。

本次实验使用Kruskal算法求解最小生成树。

Kruskal算法基于一个贪心的思想:每次选择权值最小的边,直到生成树中包含所有的节点。

具体算法如下:1.根据给定的连通图构造一个边的集合E,E中包含图中所有的边。

2.将E中的边按照权值从小到大排序。

3.依次遍历排序后的边,如果该边的两个节点不在同一个连通分量中,则选择该边,并将这两个节点合并到一个连通分量中。

4.重复第3步,直到生成树中包含所有的节点。

实验步骤及结果:1.根据给定的连通图构造边的集合E,并将E中的边按照权值从小到大排序。

2.初始化一个空的集合T作为最小生成树的边集合。

3.依次遍历排序后的边,如果该边的两个节点不在同一个连通分量中,则选择该边,并将这两个节点合并到一个连通分量中,同时将该边添加到集合T中。

4.重复第3步,直到生成树中包含所有的节点。

实验结果分析:通过Kruskal算法,可以得到带权无向连通图的最小生成树。

最小生成树具有多个优点,如能够保证连通、权值最小、无回路。

在实际应用中,最小生成树常常用于网络设计、集成电路布线等领域。

实验总结:通过本次实验,我掌握了最小生成树的概念和Kruskal算法的原理和实现方法。

实验中,我通过定义边的数据结构和构造边的集合,实现了Kruskal算法求解最小生成树。

通过实验,我深刻认识到数据结构在解决实际问题中的重要性和实用性。

最小生成树作为一种常用的图论算法,在实际应用中具有广泛的应用和重要的价值。

掌握了最小生成树的概念和算法,我相信能够在今后的学习和工作中更好地应用数据结构算法解决实际问题。

图的基本操作与kruskal最小生成树实验报告

图的基本操作与kruskal最小生成树实验报告

数据结构实验五图的基本操作一、实验目的1、使学生可以巩固所学的有关图的基本知识。

2、熟练掌握图的存储结构。

3、熟练掌握图的两种遍历算法。

二、实验内容[问题描述]对给定图,实现图的深度优先遍历和广度优先遍历。

[基本要求]以邻接表为存储结构,实现连通无向图的深度优先和广度优先遍历。

以用户指定的结点为起点,分别输出每种遍历下的结点访问序列。

【测试数据】由学生依据软件工程的测试技术自己确定。

三、实验前的准备工作1、掌握图的相关概念。

2、掌握图的逻辑结构和存储结构。

3、掌握图的两种遍历算法的实现。

四、详细设计五、源程序#define INFINITY 10000#define MAX_VERTEX_NUM 40#define MAX 40#include<stdlib.h>#include<stdio.h>#include<conio.h>#include<string.h>typedef struct ArCell{int adj;}ArCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; typedef struct{char name[20];}infotype;typedef struct{infotype vexs[MAX_VERTEX_NUM];AdjMatrix arcs;int vexnum,arcnum;}MGraph;int LocateVex(MGraph *G,char* v){ int c=-1,i;for(i=0;i<G->vexnum;i++)if(strcmp(v,G->vexs[i].name)==0){c=i;break;}return c;}MGraph * CreatUDN(MGraph *G)//初始化图,接受用户输入{int i,j,k,w;char v1[20],v2[20];printf("请输入图的顶点数,弧数:");scanf("%d%d",&G->vexnum,&G->arcnum);printf("结点名字:\n");for(i=0;i<G->vexnum;i++){printf("No.%d:",i+1);scanf("%s",G->vexs[i].name);}for(i=0;i<G->vexnum;i++)for(j=0;j<G->vexnum;j++)G->arcs[i][j].adj=INFINITY;printf("请输入一条边依附的两个顶点和权值:\n");for(k=0;k<G->arcnum;k++){printf("第%d条边:\n",k+1);printf("起始结点:");scanf("%s",v1);printf("结束结点:");scanf("%s",v2);printf("边的权值:");scanf("%d",&w);i=LocateVex(G,v1);j=LocateVex(G,v2);if(i>=0&&j>=0){G->arcs[i][j].adj=w;G->arcs[j][i]=G->arcs[i][j];}}return G;}int FirstAdjVex(MGraph *G,int v){int i;if(v<=0 &&v<G->vexnum){ //v合理for(i=0;i<G->vexnum;i++)if(G->arcs[v][i].adj!=INFINITY)return i;}return -1;}void VisitFunc(MGraph *G,int v){printf("%s ",G->vexs[v].name);}int NextAdjVex(MGraph *G,int v,int w){int k;if(v>=0 && v<G->vexnum && w>=0 && w<G->vexnum)//v,w合理{for( k=w+1;k<G->vexnum;k++)if(G->arcs[v][k].adj!=INFINITY)return k;}return -1;}int visited[MAX];void DFS(MGraph *G,int v)//从第v个顶点出发递归地深度优先遍历图G {int w;visited[v]=1;VisitFunc(G,v);//访问第v个结点for(w=FirstAdjVex(G,v);w>=0;w=NextAdjVex(G,v,w))if(!visited[w]){DFS(G,w);printf("%d ",G->arcs[v][w].adj);}}void DFSTraverse(MGraph *G,char *s)//深度优先遍历{int v,k;for(v=0;v<G->vexnum;v++)visited[v]=0;k=LocateVex(G,s);if(k>=0&&k<G->vexnum){for(v=k;v>=0;v--){if(!visited[v])DFS(G,v);}for(v=k+1;v<G->vexnum;v++)if(!visited[v])DFS(G,v);}}typedef struct Qnode{int vexnum;struct Qnode *next;}QNode,*QueuePtr;typedef struct{QueuePtr front;QueuePtr rear;}LinkQueue;int InitQueue(LinkQueue *Q){Q->front=Q->rear=(QueuePtr)malloc(sizeof(QNode)); if(!Q->front)exit(0);Q->front->next=NULL;return 1;}void EnQueue(LinkQueue *Q,int a ){QueuePtr p;p=(QueuePtr)malloc(sizeof(QNode));if(!p)exit(0);p->vexnum=a;p->next=NULL;Q->rear->next=p;Q->rear=p;}int DeQueue(LinkQueue *Q,int *v){ QueuePtr p;if(Q->front==Q->rear){printf("结点不存在!\n");exit(0);}p=Q->front->next;*v=p->vexnum;Q->front->next=p->next;if(Q->rear==p)Q->front=Q->rear;return *v;}int QueueEmpty(LinkQueue *Q){if(Q->rear==Q->front)return 0;return 1;}int Visited[MAX];void BFSTraverse(MGraph *G,char *str)//广度优先遍历{int w,u,v,k;LinkQueue Q,q;for(v=0;v<G->vexnum;v++) Visited[v]=0;InitQueue(&Q);InitQueue(&q);k=LocateVex(G,str);for(v=k;v>=0;v--)if(!Visited[v]){Visited[v]=1;VisitFunc(G,v);EnQueue(&Q,v);//v入队while(!QueueEmpty(&Q)){DeQueue(&Q,&u);//出队for(w=FirstAdjVex(G,u);w>=0;w=NextAdjVex(G,u,w)) if(!Visited[w]){Visited[w]=1;VisitFunc(G,v);EnQueue(&Q,w);}}}for(v=k+1;v<G->vexnum;v++)if(!Visited[v]){Visited[v]=1;VisitFunc(G,v);EnQueue(&Q,v);//v入队while(!QueueEmpty(&Q)){DeQueue(&Q,&u);//出队for(w=FirstAdjVex(G,u);w>=0;w=NextAdjVex(G,u,w)) if(!Visited[w]){Visited[w]=1;VisitFunc(G,v);EnQueue(&Q,w);}}}}void main(){MGraph *G,b;char v[10];G=CreatUDN(&b);printf("请输入起始结点名称:");scanf("%s",v);printf("\n深度优先遍历:\n");DFSTraverse(G,v);printf("\n广度优先遍历:\n");BFSTraverse(G,v);getch();}六、测试数据及调试实验六图的应用一、实验目的1、使学生可以巩固所学的有关图的基本知识。

求最小生成树(Kruskal算法)实验报告【范本模板】

求最小生成树(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条边,所使用的贪婪准则是:从剩下的边中选择一条不会产生环路的具有最小耗费的边加入已选择的边的集合内。

数据结构实验最小生成树

数据结构实验最小生成树

数据结构实验最小生成树数据结构实验报告最小生成树问题一、问题描述:若要在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. 掌握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算法适用于稀疏图,因为它的时间复杂度与边的数量成正比。

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。

最小生成树实验报告

最小生成树实验报告

最小生成树实验报告最小生成树(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从实验结果来看,无论是规模较小的图还是规模较大的图,我们都能够得到最小生成树,并且所得到的结果是正确的。

数据结构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结尾。

生成树实验报告总结

生成树实验报告总结

一、实验目的本次实验的主要目的是通过实际操作加深对生成树概念的理解,掌握生成树的构建方法,包括Kruskal算法和Prim算法,并学会使用程序解决实际问题。

二、实验内容1. Kruskal算法Kruskal算法是一种基于边优先的策略来构建最小生成树的算法。

它将所有边按照权值从小到大排序,然后依次选择权值最小的边,同时检查新加入的边是否会构成环。

若不会构成环,则将这条边加入最小生成树中。

2. Prim算法Prim算法是一种基于顶点优先的策略来构建最小生成树的算法。

它从一个顶点开始,逐步扩大最小生成树,直到所有顶点都被包含。

在每次迭代中,算法都会选择一个与已构建的最小生成树连接的最小权值边。

三、实验步骤1. 设计实验环境(1)搭建实验平台:使用C++编程语言,实现Kruskal算法和Prim算法。

(2)设计数据结构:邻接矩阵和邻接表。

2. 编写算法代码(1)Kruskal算法:```cpp// Kruskal算法实现void Kruskal(int n, adjmatrix a) {int i, j, k, u, v;for (i = 1; i <= n; i++) {for (j = i + 1; j <= n; j++) {if (a[i][j] != 0 && a[i][j] != INF) {// 初始化并查集 u = Find(i);v = Find(j);// 合并集合Union(u, v);}}}}```(2)Prim算法:```cpp// Prim算法实现void Prim(int n, adjmatrix a) { int i, j, k, u;int key[MaxNum];int inTree[MaxNum];for (i = 1; i <= n; i++) { key[i] = INF;inTree[i] = false;}key[1] = 0;inTree[1] = true;while (true) {k = -1;for (i = 1; i <= n; i++) {if (!inTree[i] && key[i] < INF) {if (k == -1 || key[i] < key[k]) {k = i;}}}if (k == -1) {break;}inTree[k] = true;for (j = 1; j <= n; j++) {if (!inTree[j] && a[k][j] != INF && a[k][j] < key[j]) { key[j] = a[k][j];}}}}```3. 编译并运行程序(1)使用C++编译器编译代码。

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

学生实验报告
学院:软件与通信工程学院
课程名称:离散数学(软件)
专业班级:12软件2班
*名:**
学号:*******
学生实验报告(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 6
struct 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距离为6
node *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_val
tmptr->find=1; //并标记该顶的边已选择
return tmptr;
}
三、结论
1、实验结果
2、分析讨论
在编写这个程序时,我们先要非常熟悉kruskal算法,kruskal算法总共选择n-1条边,所使用的贪婪准则是:从剩下的边中选择一条不会产生环路的具有最小耗费的边加入已选择的边的集合内。

然后根据这个算法用c++实践出来,程序长而又复杂,需要多多联系算法,以后的时间中还得多多练习。

四、指导教师评语及成绩:
成绩:指导教师签名:
批阅日期:。

相关文档
最新文档