贪心算法设计实验报告

1、算法设计技巧与分析课程实验报告实验名称贪心算法的运用实验序号姓名系院专业班级学号实验口期指导教师成绩一、实验目的掌握贪心算法的基本概念和两个基本要素熟练掌握贪心算法解决问题的基本步骤学会利用贪心算法解决实际问题二、实验内容与要求1,实现贪心算法的经典运用Krnskal算法(最小生成树)2,实现贪心算法的经典运用Pnm算法(最小生成树)三、实验设备地点:科技楼网络实验室602硬件环境:IntelPentiumProcessor1.8G,512M内存,windows操作系统软件环境:VC+6.0五、实验步骤用Kiuskal算法实现最小生成树算法描述:假设WN=(V,E)是一

2、个含有n个顶点的连通网,则按照克鲁斯卡尔算法构造最小生成树的过程为:先构造一个只含n个顶点,而边集为空的子图,若将该子图中各个顶点看成是各棵树上的根结点,则它是一个含有a棵树的一个森林。之后,从网的边集E中选取一条权值最小的边,若该条边的两个顶点分属不同的树,则将其加入子图,也就是说,将这两个顶点分别所在的两棵树合成一棵树:反之,若该条边的两个顶点己落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。依次类推,直至森林中只有一棵树,也即子图中含有n-1条边为止。G下面给出C语言代码实现及说明本程序对树的存储主要是以边为存储对象,即边的结构体里面有这样几个参数:1,边的权值。

3、2,边的一个顶点。3,边的另一个顶点。4,边是否属于生成树的一条边(即最小生成树边标志)。由该程序的存储结构决定了该算法比较适用于边稀疏的情形,至于边稠密的情况会在卜.面的Pnm算法中给出。在Kiwskal算法中有两个比较重要的部分1,对边按权重排序。2,对一条边加入子树后是否会产生回路的判断即判断边的两个节点是否在同一个树中(集合里)对于问题1:可以有各种排序算法,读者可以自行选择自己喜欢的排序算法来替换代码中的排序算法。(本处使用选择排序算法(效率较低),读者可以自己修改为快速排序或者是对排序)下面主要讲解解决问题2,解决这个问题一般借用不相交集的思想,即在本程序中每次以同集合

4、中所有点的编号最小的数来标识本集合。(对于根节点即标号最小的节点则标记为0)例如对于上图实例,下面给出详细的不相交集的维护过程(给出前几步的详细说明)a,初始状态(ABCDEFG分别在数组的第1,2,3,4,5,6,7)0号位空置(均为0)0ABCDEFG0b,选择第一彳0条边A-D(将0D的标记改0为1)(因为0D最短)0000ABCDEFG0000I000对表进行维护(维护后仍同上表,因为还没有两个集合合并)0ABCDEFG0000I000C,选择第二条边C-E(修改上表)0ABCDEFG0000I300对上表进行维护(任同上表,因为还没有两个集合合并)0ABCDEFG0

5、000I300D,选择第三条边(D-F)(根据条件DF两点不再同一集合,改边可选)然后就合并DF两点所在的集合D的前去是1,即A标记为0,E的标记也为0,合并因为61所以表修改如下0ABcDEFG00001310以后几步均如上判断两点是否在一个集合从而判断改边是否可取,并维护上表下面附上源代码Kiuskal算法的实现09网一殷赛0910322113输入:图G(用结构体数组来存储每条边,包含每条边的节点)输出:图G的最小生成树树*:$:*:$:*:$:*:$:*:$:*:$:*:$:*:$:*:$:*:$:*:$:*:$:*:$:*左*左*:$:*:$:*:$:*/#iiiclude

6、#iiicludetypedefstiuctEdge(chardot_l;chardot_2;intweight;intleap;Edge;Edge*selectioiisort(Edge*arrayintn)选择排序(对边按权重由高到低排序)(intijminjemp;fbi(i=0;in;i+)nun=i;fbr(j=i+lJaiTayj.weight)mm=j;iRmni!=i)temp=anayi.weight;airayi.weight=arraynini.weight;aiTayfnun.weight=temp;temp=anayi.d

7、ot_1;airayi.dot_1=aiTayinin.dot_1;arraymin.dot_1=temp;temp=anayi.dot_2;arrayi.dot_2=arrayniindot_2;arraymin.dot_2=temp;letuinairay;Edge*Kinskal(Edge*Graph,iiitnum_num_v)/克鲁斯卡尔算法实现(intm.njest;mtfoi(i=O;inum_e;i+)fbr(j=l;jnum_v+1;j+)if(Giaphi.dod=V0j)m=j;if(Graphi.do

8、t_2=V0j)n=J;if(V1m!=V1n&m!=V1n&n!=V1m)/Z如果边的两个顶点不再一个集合则边是生成树的边(注意首节点的标记和集合里非首节点的标记不同)Graphi.leap=l;if(Vln=O)JIif(nVln)VlVlm=Vln;elseVlVln=Vlm;)维护不相交集k=l;对每个节点都检查是否为标记合格节点while(knum_v+1)一样的(即标记符合标准的节点)(t=Vlk;wlule(Vlt!=O)(t=Vlt;Vlk=t;)k+;if(V1m=0&V1n=0)/如果边的两个顶点是两个集合的首节点则可以合并Graphi.

9、leap=l;Vlm=n;elseVln=m;维护不相交集k=l;while(knum_v+1)if(Vlk!=O)(t=Vlk;wlule(Vlt!=O)(t=Vlt;k+;/*printf(”不相交集的情况:iiH);fbr(test=1;testnum_v+1;test+)pnntf(”4c”,V0test);fbr(test=1;testnum_v+1;test+)printf(,l%-4dfV1test);returnGraph;voidniainQ(intiJ,num_vjium_e,cost=0;Edge*Graph=NULL;int*V=N

10、ULL;pnntf(”请输入土中有多少个顶点!n”);scanf(n%d,&num_v);V=(mt*)malloc(sizeof(iiit*)*2);fbr(i=0;i2;i+)Vi=(iiit*)malloc(sizeof(mt)*(num_v+1);fbr(i=0;i2;i+)Rr(j=O;jvnum_v+l;j+)Vij=O;fbr(i=1;inum_v+l;i+)pnntf(”请输入第1个顶点二1);scanff%c,&VOi);printfC请输入图中有多少条边!n);scanf(n%d,&num_e);Giaph=(Edge*)malloc(sizeof(Edge)

11、*num_e);fbr(i=O;inum_e;i+)pnntf(”请输入第1条边的权值和两个顶点!n”,i+l);scanf(n%d%c%c”.&Graphi.weight,&Graphi.dot_l,&Graphi.dot_2);Graphi.leap=O:Graph=selectionsoit(Graphjium_e);以上部分是存储图/Graph=Kiiiskal(Graph.num_e,V;num_v);printf(构成最小生成树的边和顶点分别是:);pnntf(”顶点1顶点2边山”);fbr(i=O;inum_e;i+)if(Graphi.leap=1)printR

12、”%c%c%dn,Graphi.dot_LGraphi.dot_2,Graphi.weight);cost=cost+Graphi.weight;printf(”最小生成树的权值是:%dn,cost);请输入土中有多少个顶点*7敏入篡1个顶京圄$入患6j-顶修F请辙入图中有参少条边?11请输入第i条边的权值和两个顶点!5AD请输入第2条边的权值和两个顶点!AB请输入第3条边的权值和两个顶点!9BD请输入第4条边的权值和两个顶点!BC请输入第5条边的权值和两个顶点!BE请输入第6条边的权值和两个顶点!SCE请输入第条边的权值和两个顶点!帝塞第8条边的权值和两个顶点

13、!整备人第9条边的权值和两个顶点!EF请输入第博条边的权值和两个顶点!EG请输入第11条边的权值和两个顶点!11FG构成最、生成树的边和点分别是;A-CA-C-D一B-A-最泉星成树的权值是:3PressanykeytocontinueDEFEBG用Prun算法实现最小生成树算法描述:假设V是图中顶点的集合,E是图中边的集合,TE为最小生成树中的边的集合,则prmi算法通过以下步骤可以得到最小生成树:1:初始化:U=u0,TE=f此步骤设立一个只有结点u0的结点集U和一个空的边集TE作为最小生成树的初始形态,在随后的算法执行中,这个形态会不断的发生变化

14、,直到得到最小生成树为止。2:在所有uGU,vev-U的边(u,v)GE中,找一条权最小的边(u0,v0),将此边加进集合TE中,并将此边的非U中顶点加入U中。此步骤的功能是在边集E中找一条边,要求这条边满足以下条件:首先边的两个顶点要分别在顶点集合U和V-U中,其次边的权要最小。找到这条边以后,把这条边放到边集TE中,并把这条边上不在U中的那个顶点加入到U中。这一步骤在算法中应执行多次,每执行一次,集合TE和U都将发生变化,分别增加一条边和一个顶点,因此,TE和U是两个动态的集合,这一点在理解算法时要密切注意。3:如果U=V,则算法结束;否则重复步骤2。可以把本步骤看成循环终止

15、条件。我们可以算出当U=V时,步骤2共执行了n-1次(设n为图中顶点的数目),TE中也增加了n-1条边,这n-1条边就是需要求出的最小生成树的边(图任如上图)下面给出具体c语言代码和详解该代码的存储结构是邻接矩阵上三角用来存储最小生成树的边,树边用-1标记,下三角用来存储原图,方便输出最小生成树上图的最后邻接矩阵如下:(具体实现和解释见代码)(INF代表无穷,即不相邻)0-1INF-1INFINFINF70INFINF-1INFINFINF80INF-1INFINF59INF0INF-1INFINF75150INF-1INFINFINF680INFINFINFINFINF9110/

16、*09网一殷赛0910322113Prun算法的实现输入:图G输出:图G的最小生成树*/#iiiclude#iiiclude#defiiieINF32767*Pnm算法最重要的部分在于从可以挑选的边中间挑选出最小值并且对加入后会产生回路的边标记为不可选(此代码中将该边权值标记为INF即无穷大)每选中一条边就会加入一个点(就必须对与该点连接的边进行维护,即多产生回路边标记为无穷)找最小边则是从上三角中所有可选的行和列中选择选中的树边则标记为1(其权值从下三角读出)**/voidPrim(int*Graph.iiitnum_v)/转化为对上三角的维护(intiJJeap=

17、Ojemp;intm,njiiin;int*a=(int*)malloc(sizeof(int)*num_v);for(i=0;inum_v;i+)ai=0;a0=l;wliile(leap!=num_v-l)nun=INF:foi(i=0;inum_v;i+)/搜索上三角中的最小值/Iif(ai=l)/Ifbr(j=i+ljGraphi0&Graphi0O)(nun=GraphiIj;m=j;n=i;tenip=0;)for(j=OjviJ+)列中搜索if(minGraphji&Graphji0)nun=Graphji;m=j;n=i;tenip=l;)if(temp=O

18、)为了区别出是在行还是在列中搜索到的元素Graphnm=-1;elseGraphmn=-1;for(i=0;i0)fGraphfim=INF;for(i=m+l;i0)fGraphmi=INF:am=l;/*foi(i=0;inum.v;i+)/检查矩阵中在那些行(列)可以选择最小值(即那些列和行是候选行和列)/*for(i=0;inum_v;i+)/检验对上三角的维护,和下三角是否修改了(下三角保存了原树和用于输出最小生成树)Ifbr(j=0;jnum_vj+)pnntff%4dt”,Graphij);pnntf(nnM);*/leap+;voidmain。(intij;int

19、num_v4ium_e;int*Graph=NULL;char*V=NULL;charch_l,ch_2;intweight;intm.n;printf(请输入图的顶点数:);scanf(n%d,&num_v);V=(chai*)nialloc(sizeof(char)*num_v);Graph=(mt*)malloc(sizeof(mt*)*num_v)-J!动态生成维数组用来存储图(邻接矩阵)fbr(i=O;inum_v;i-H-)Graphi=(mt*)malloc(sizeof(int)*num-v);for(i=0;inum_v;i+)/初始化矩阵Graphij=INF;fbr(i=O;inum_v;i-H-)Graphii=O;fbr(i=O;inum_v;i-H-)pnntf(”请输入第1个顶点:”,i+1);scanff%c”,&Vi);pnntf(请输入图的边数:”);scanf(%d,&num_e);fbr(i=O;inum_e;i-H-)pnntf(”请输入第1条边的顶点和权值二i+1);scan町%c%c%d”.&ch_l,&ch_2,&weight);fbr(j=0;jnum_vj+

THE END
1.贪心算法实例详解(转)Kobe10原文地址:http://blog.csdn.net/qq_32400847/article/details/51336300 这篇帖子总结归纳很到位,值得学习。 分类: 数据结构和算法 好文要顶 关注我 收藏该文 微信分享 Kobe10 粉丝- 27 关注- 25 +加关注 0 0 升级成为会员 ? 上一篇: 贪心算法(转) ? 下一篇: (贪心)加油站绕圈问题 https://www.cnblogs.com/Kobe10/p/6349135.html
2.数学模型数学模型-贪心算法及实例.ppt,贪心算法 问题引入: 有下面几种面值的硬币:一元、五角、一角、五分、一分,假设要付给顾客2.89元的零钱,要求用最少的硬币。 顾名思义,贪心算法总是作出在当前看来最好的选择。也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某https://max.book118.com/html/2019/0814/6040151111002054.shtm
3.贪心算法教程:入门到实践的简洁指南贪心算法的应用实例与案例分析 背包问题 背包问题是一个经典的优化问题,涉及到决定哪些物品放入背包以最大化其总价值,同时不超过背包的重量限制。贪心算法可以用于解决“完全背包问题”,通过按价值/重量的比例排序物品并逐个加入背包,直到无法再加入为止。 示例代码: https://www.imooc.com/article/351183
4.贪心算法入门详解,经典实例分析贪心算法入门详解,经典实例分析 贪心算法的字面有本是形容人的“贪心”一词,着实有些引人注目,有人说贪心算法是世界上最简单的算法,原因很简单:所有人都很“贪心”,根本不用学,不过,算法会怎样贪心呢? “贪心”的人,事事都想要得到眼前最好的那个,看不到长远的东西,也不为将来最终结果做打算,换句话说,就是https://blog.popkx.com/2307/
5.采用C++实现区间图着色问题(贪心算法)实例详解IT知识教程采用C++实现区间图着色问题(贪心算法)实例详解 本文所述算法即假设要用很多个教室对一组活动进行调度。我们希望使用尽可能少的教室来调度所有活动。采用C++的贪心算法,来确定哪一个活动使用哪一间教室。 对于这个问题也常被称为区间图着色问题,即相容的活动着同色,不相容的着不同颜色,使得所用颜色数最少。https://www.300.cn/itzspd/503783.html
6.算法详解(卷3)——贪心算法和动态规划在本系列图书的卷1中,我们看到了这个算法范例的很多实例:MergeSort和QuickSort算法、Karatsuba的O(n1.59)时间级的两个n位整数相乘算法、Strassen的O(n2.71)时间级的两个n×n矩阵的相乘算法等。 本系列图书卷3的前半部分讨论贪心算法的设计范例。贪心算法的准确定义是什么?关于这个问题,可以说是“唾沫和墨汁横飞”https://www.epubit.com/bookDetails?id=UB831756653320d
7.贪心算法:使用贪心算法实现哈夫曼编码为什么这里贪心算法得不到最优解呢?我们第一步从S->A和第一步从S->B,下一步面对的顶点和边是不一样的。也就是我们前面的选择会影响后面的选择,所以得不出最优解。 2、贪心算法实例分析 接下来,我们再看几个能够使用贪心算法求最优解的问题。 https://www.jianshu.com/p/9caa72f4ac97
8.力扣入门经典题型题目之贪心算法例子和解法:3个孩子饥饿程度为1,2,3,两块饼干大小为1,1。先分给饥饿程度最小的孩子,剩下1块,无法分给更多人了,结果为1. 贪心策略为先将两个数组排序,为了让尽可能多的吃饱 先喂饱饥饿度小的孩子最小的饼干,以此类推。 代码: C++ classSolution{public:intfindContentChildren(vector<int>&children,vector<https://zhuanlan.zhihu.com/p/451744848
9.浅谈Python实现贪心算法与活动安排问题python本篇文章主要介绍了浅谈Python实现贪心算法与活动安排问题,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧 贪心算法 原理:在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。贪心算法不是对所有问题都能得https://www.jb51.net/article/130987.htm
10.Java实现贪心算法实例介绍51CTO博客Java 实现贪心算法实例介绍 1.引言 本文将介绍如何用 Java 实现贪心算法。 2.贪心问题 通常一个数学问题会有几种解法。可以迭代解决,也可以用分治法(快速排序算法)或者动态规划(背包问题)这样的高级方法。 大多数情况我们都在寻找最优解,但可悲的是并非每次都能得到期望的结果。某些情况下,即使是次优解也很有用https://blog.51cto.com/u_15127686/2829966
11.贪心算法WOODENSTICKS实例代码贪心算法 WOODEN STICKS 实例代码,需要的朋友可以参考一下 贪心算法 WOODEN STICKS2020-09-05 上传大小:37KB 所需:18积分/C币 用贪心算法解单源最短路径问题 用贪心算法解单源最短路径问题 明确单源最短路径问题的概念;利用贪心算法解决单源最短路径问题;并通过本例熟悉贪心算法在程序设计中的应用方法。 https://www.iteye.com/resource/weixin_38720756-12814957
12.使用贪心算法的分数背包问题Mangs使用贪心算法的分数背包问题 目录:- 一、简介 应用实例 三、算法说明 实施 推论/结论 简介:- 分数背包问题是一个组合优化问题。这意味着它涉及到 n 个在数学意义上具有不同特征(或权重和值)的对象。目标是将这些物品分成几个不同大小的背包,同时最大限度地提高总效用。在这个问题中,总效用由比率值/重量表示,https://devpress.csdn.net/python/62fb8e2a7e6682346618f099.html
13.算法分析与设计期末答案2023秋51.关于Prim算法和Dijkstra算法,以下说法正确的是( )。A:两个算法都需要引入一个数组用于记录一个点是否被访问过 B:两个算法在不优化时的时间复杂度都为O(V^2),V表示顶点的个数 C:两个算法都是贪心算法的经典实例 D:两个算法都包含了松弛操作,在松弛时对相应的数据结构进行更新 内容已经隐藏,点击付费后https://www.wkebb.com/c/776b56604264529595bfd59c2f472142.html
14.贪心算法WOODENSTICKS实例代码贪心算法 WOODEN STICKS 实例代码 Problem Description There is a pile of n wooden sticks. The length and weight of each stick are known in advance. The sticks are to be processed by a woodworking machine in one by one fashion. It needs some time, called setup time, for the machine to https://www.xiuzhanwang.com/a1/Cyuyan/4505.html
15.C++算法集锦(14):贪心算法腾讯云开发者社区贪心算法可以理解为一种特殊的动态规划为题,拥有一些更加特殊的性质,可以进一步降低动态规划算法的时间复杂度。 来看几道题目熟悉一下这种“不断寻求局部最优”的算法。 跳跃游戏 I 输入一个非负整数数组nums,数组元素nums[i]表示的是:如果你站在位置 i ,最多能够往前跳几步。 现在你站在第一个位置nums[0],试https://cloud.tencent.com/developer/article/1879118
16.贪心算法(C语言实现)C语言贪心算法适用的问题:局部最优策略能产生全局最优解。但是实际上,贪心算法适用的情况很少。一般来说,对一个问题分析是否适用于贪心算法,可以先选择该问题下的几个实际实例进行分析,就可做出判断。 C语言贪心算法的一般步骤如下。 建立数学模型来描述问题。 https://www.54benniao.com/a/vts0zi.html