ImageVerifierCode 换一换
格式:DOCX , 页数:22 ,大小:171.52KB ,
资源ID:18415369      下载积分:12 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/18415369.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(改进的最小生成树算法Word文档格式.docx)为本站会员(b****3)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

改进的最小生成树算法Word文档格式.docx

1、最小生成树的应用非常的广,如矿井通风设计和改造最优化方面以及如何搭建最短的网络线缆, 构建造价最低的通讯网络 。关键词:java,最小生成树;破圈法一、 问题描述一般都采用prim算法或者 kruskal算法,两个算法都很直接。prim算法其实就是disj算法的变形,只是更新策略和判断策略不同而已。kruskal采用了不相交集和堆,写出的算法也很简洁并且很好理解。而这两者都是通过添加边来构造树,最小生成树还有一种大类就是破圈法。本文我们探究的是用破圈法来构造树,即连续删除某些边,从而破坏图中的回路,直到图中不存在回路为止,此时的图就是生成树。二、 需求分析 根据提示使用删除边的方法,我们想到了

2、破圈算法。破圈算法是1975年由我国数学家管梅谷教授提出来的。 破圈法基本思想:在给定的图中任意找出一个回路,删去该回路中权最大的边。然后在余下的图中再任意找出一个回路,再删去这个新找出的回路中权最大的边,一直重复上述过程,直到剩余的图中没有回路。这个没有回路的剩余图便是最小生成树。 算法的基本思想:先将图G 的边按权的递减顺序排列后, 依次检验每条边, 在保持连通的情况下, 每次删除最大权边, 直到余下n- 1 条边为止。1. 性能需求1) 构造数据的输入形式和范围输入顶点数为int类型,范围为0-100。2) 数据结构采用邻接矩阵存储图。2. 功能需求1在给定的赋权的连通图上任意找一个圈。

3、2在所找的圈中去掉一条权数最大的边(若有两条或者两条以上权数相等的 边,则任意去掉其中一条)。3 重复1、2操作,直至余下的图为最小生成树。3. 问题假设假设本题涉及的无向图是一个连通图。三、 准备知识1算法的理论基础:定理1: 任意图G 有支撑树的充分必要条件是图G 是连通的。定理2: 图G= ( V, E) 是一个树的充分必要条件是G 是连通图, 且e=n- 1 。2最小生成树最小生成树:一个有n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有n 个结点,并且有保持图连通的最少的边,如图1所示。图1 最小生成树示意图设G = (V, E)是无向连通带权图,即一个网络。E 中

4、的每一条边(v, w)的权为W(v, w)。如果G 的子图G是一棵包含G 的所有顶点的树,则称G为G 的生成树。生成树上各边权的总和称为生成树的耗费。在G 的所有生成树中,耗费最小的生成树称为G 的最小生成树。1避圈法避圈法的主要思想就是:开始选一条最小权的边,以后每一步中,总从与已选边不构成圈的那些未选边中,选择一条权最小的(每一步中,如果有两条或两条以上的边都是权值最小的边,则从中任选一条)。避圈法主要分为两种:Prim 算法和Kruskal 算法,下面分别进行介绍。a. Prim 算法设G = (V, E)是连通带权图,V = 1,2,n。构造G 的最小生成树Prim 算法的基本思想是:

5、首先置S = 1,然后,只要S 是V 的真子集,就进行如下的贪心选择:选取满足条件iS, jV S,且cij最小的边,将顶点j 添加到S 中。这个过程一直进行到S = V 时为止。在这个过程中选取到的所有边恰好构成G 的一棵最小生成树。图2显示了某一带权图。最小生成树的生成过程如下:13;c =136;c = 464;c = 232;c = 525;c = 3最终得到的最小生成树如图3所示。图2 带权图G图3 带权图G 的最小生成树示意图b. Kruskal 算法给定无向连通带权图G = (V, E), V = 1,2,.,n。Kruskal 算法构造G 的最小生成树的基本思想是:(1) 将G

6、 的n 个顶点看成n 个孤立的连通分支,并将所有的边按权从小到大排序;(2) 从第一条边开始,依据每条边的权值递增的顺序检查每一条边,并按照下述方法连接两个不同的连通分支:当查看到第k 条边(v, w)时,如果端点v 和w 分别是当前两个不同的连通分支T1 和T2 的端点时,就用边(v, w)将T1 和T2 连接成一个连通分支,然后继续查看第k+1 条边;如果端点v 和w 在当前的同一个连通分支中,就直接查看第k+1 条边,这个过程一个进行到只剩下一个连通分支时为止。此时,已构成G 的一棵最小生成树。仍以图2 所示的带权图G 为例说明其最小生成树的生成过程,生成过程如下所示:46;23;最终得

7、到的最小生成树和图3所示是一样的。2破圈法破圈法可以描述如下:(1) 如果我们给的连通图G 中没有回路,那么G 本身就是一棵生成树;(2) 若G 中只有一个回路,则删去G 的回路上的一条边(不删除结点),则产生的图仍是连通的且没有回路,则得到的子图就是图G 的一棵生成树;(3) 若G 的回路不止一个,只要删去每一个回路上的一条边,直到G 的子图是连通没有回路且与图G 有一样的结点集,那么这个子图就是一棵生成树。由于我们破坏回路的方法可以不一样,所以可得到不同的生成树,但是在求最小生成树的时候,为了保证求得的生成树的树权最小,那么在删去回路上的边的时候,总是在保证带权图仍连通的前提下删掉权值较大

8、的边,保留权值较小的边。破圈法就是在带权图的回路中找出权值最大的边,将该边去掉,重复这个过程,直到图连通且没有圈为止,保留下来的边所组成的图即为最小生成树。下面仍利用图1.1.2 对破圈法进行说明。首先是去除权值大的边,并且检测去除该边后整个图是否连通,对于图2 来说,即第一步去掉权值为6 的边,如图4 所示。图4 去掉权值为6 的G 的示意图 从图中可以看出,去掉权值为6 的边后整个图仍是连通的。所以接下来去除权值为5 的边,并且检测去除该边后图是否连通,结果如图5 所示。由图可知,去掉所有权值为5 的边会造成图G不连通,因此2 3;c 5这条边是必须保留的。然后再去除权值为 4的边。由于权

9、值为1、2、3、4的边分别连接着独立的节点,故都必须保留,得到的最小生成 图5 去掉权值为5的G的示意图 树结果与图3也是一样的。3 避圈法与破圈法比较 Prim算法是从空图出发,将点进行二分化,从而逐步加边得到最小生成树。它是近似求解算法,虽然对于大多数最小生成树问题都能求得最优解,但相当一部分求得的是近似最优解,具体应用时不一定很方便。但是它可以看作是很多种最小树算法的概括,在理论上有一定的意义。Kruskal算法也是从空图出发。它是精确算法,即每次都能求得最优解,但对于规模较大的最小生成树问题,求解速度较慢。破圈法是从图G出发,逐步去边破圈得到最小生成树。它最适合在图上工作,当图较大时,

10、可以几个人同时在各个子图上工作,因此破圈法在实用上是很方便的。四、 算法和数据结构设计1算法分析1概要设计: 当仔细研究了课题并且考虑过后,我们都想到了破圈法,通过删边来构造最小生成树a. 用拓扑分类算法,找到图中的圈。具体就是依次找到图中度为1的顶点(可以保存在队列里),删除之(这里的删除是暂时的,下次遍历还要还原这些点),然后与其邻接的顶点的入度-1,这样往复操作,直到图中已不存在入度为1的顶点,即所有的顶点的度都=2,那么剩下的边就都在环里了。当然,如果没剩下边,说明没有环,算法结束。b. 剩下的边就都是环中的边了,找一个权最大的删去即可。c. 再进行1操作,直到图中无圈,即所有的圈都已

11、破掉,剩下的就是最小生成树了。2详细设计:a. 算法中的主要的主程序:void intialGraph():用于创建图public boolean IsConnect():并查集判断图连通性 public boolean IsConnectedGraph():检查是否为连通图 public void createGraph(Edge d):根据边集组创建一个图 public ListcreateEdgeList():由邻接矩阵生成边集列表 int vertices():返回图的定点数 int edges():返回图的边数 void putEdge(Edge e):填点边 void remove

12、Edge(int i,int j):删除边 boolean findEdge(int i ,int j):查找边 void output():输出图Integer depthFirstSearch(int v):深度优先遍历 void breakLoopBST():删边获得最小生成树b. 主程序main()的基本流程1) 创建图对象,自动调用构造方法初始化,输入邻接矩阵2) 调用破圈法方法breakLoopBST(),生成最小生成树3) 调用output()输出最小生成树的邻接矩阵4) 程序结束1建立模型先将图G 的边按权的递减顺序排列, Ei 为删除边集。具体步骤为第1 步: 令i=1, E

13、0=, G0=G;第2 步: 取边eiE ( Gi- 1) 即EEi- 1, 令Ei=Ei- 1ei, 使得Gi= G EEi 连通, 且W ( ei) 权尽可能大; 第3 步: 若i a=new int nn;2-for int i=0;ifor(int i=0;i+)For(int j=0;ji+1;j+)判断图的连通性boolean IsConnectedGraph()图true或者falsei+)set1.add(i);,图顶点集合if(!set1.equals(set2),深搜得到便利点的集合,与图顶点集合比较Return false;,返回比较结果为连通性判断。else retur

14、n true;深度优先遍历ArrayListbreak深度搜索尽管能得到结果,但效率却比prim算法差了更多,借鉴prim算法并查集判断图的连通性的思想,对算法进行优化,将连通性判断改为并查集,提高效率,给出算法伪代码如下:核心算法的优化采用并查集判断连通性算法booleanIsConnect()for(inti=0;n+),初始化父亲节点l=new(createEdgeList(),以边关系更新父亲节点j=0;l.size();k=0;ki+),判断图中节点的父亲节点是否统一6-return true or false,输入图的连通性b.算法的具体实现:见附录1:算法复杂度分析经分析,影响算

15、法主要决定因素是深度遍历和并查集的递归次数,分别对采用不同方法效率进行分析如下:该算法采用深度搜索判断图的连通性的时间复杂度为:O(n2);算法采用并查集判断图的连通性的时间复杂度为:O(n(n+1)/2);由此可知,并查集极大的改进了算法效率。以顶点为4的无向图为例(邻接矩阵):0 47 82 7647 0 41 6382 41 0 72 76 63 72 0最小生成树(邻接矩阵):0 47 47 0 41 63 41 0 63 0在生成最小生成树的过程中采用深度搜索判断图的连通性递归次数为:3+3+3=9次,而使用并查集的方法判断图的连通性递归次数为:1+2+3=69次。由此可以看出,使用

16、并查集判断连通性的效率远高于深度搜索。题目拓展1) 提出问题对于我们已经实现的算法的结果,执行的算法效率依然有待高,有没有更简单的优化算法来实现生成最小生成树。2) 算法分析可以采用邻接多重表的方式来进行动态优化算法:a. 首先初始化数组和顶点b. 遍历数组,将满足条件的顶点加入集合c. 循环判断d. 在其他顶点中选择满足条件的权值最小的边 五 程序测试1. 测试1(测试不能构成图时能否得到最小生成树)顶点数必须大于大于等于2才会有边1) 输入信息:2) 预测结果至少可以得到一条边3) 实际输出结果如图4.1所示图4.1 测试1实际输出结果4) 结果分析 根据输出结果分析,当顶点数为2时只能有

17、一条边,构不成图,由于我们是采用删除边的方法,当只有一条边的时候也不用删除,直接输出。2. 测试2(测试顶点数是3最小并且为最小连通图时的情况)1) 输入信息至少需要机器狗的数目为2应该只剩下其中的两条边,并且满足是最小生成树3) 实际输出如图4.2所示图4.2 测试2实际输出结果 得到的结果确实为只有两条边构成的生成树,而且是最小生成树满足要求,符合题意。3. 测试3(测试顶点数为其他数防止偶然的情况发生)5) 输入信息6) 预测结果至少输出的结果应该为只有5条边构成的最小生成树7) 实际输出8) 结果分析 得到的经过将矩阵转换为图形,满足我们所要求的是最小生成树,并且只有5条边符合 题意。

18、六 总结1. 后期设想已完成部分完成题目要求,采用删除某些边,破坏图中的回路,直到图中不存在回路为止,此时得到的生成树就是最小生成树。这种方法与老师上课讲的prime和kruskal算法在思想上有很大的不同,后两者采用的是加边的方法,将边一条一条加入生成一棵最小生成树,而我们采用的这种俗称叫做破圈法,既是将边一条一条删除最后得到一棵最小生成树。通过实验让我们更加懂得有时候解决问题可以从相反的方向去思考,不能墨守成规,一成不变,要有创新2. 后期设想 我们能不能再进一步改进算法,实现更加高效的程序,学习算法的目的也是在于优化程序,在采用删除边的方法的同时更主要实现效率的提高,这也促使我们对于这个

19、问题要有更深的理解和认识,以及在解决问题的时候我们应该考虑的更加全面,更加具体和详细。3. 程序设计思考与体会 经过我们不懈的努力我们终于完成了本次课程设计,通过这次课程设计,我感觉到要真正做出一个程序并不很容易,但只要用心去做,总会有收获,特别是当我遇到 一个问题,想办法去解决,最后终于找到方法时,心里的那份喜悦之情真是难以形容。编写程序中遇到问题再所难免,应耐心探究其中的原因,从出现问题的地方起,并联系前后程序,仔细推敲,逐个排查。直到最终搞清为止。我们本次做的是图的最小生成树问题,该算法主要侧重于找边、删边的过程,通过这个方法求到的最小生成树和别的算法相比,主要是算法简单,结构清晰,在程

20、序实现中只是用到了数组和循环语句的知识,程序简单明了。因为破圈法与避圈法是两种不同的解题思维,通过本次课程设计让我更加知道“条条大路通罗马”,平时应该变换角度得来思考问题。七 参考文献1屈婉玲. 离散数学 M. 北京:高等教育出版社, 2008.2叶核亚. 数据结构(Java版) M. 北京:电子工业出版社, 2011.3屈婉玲. 算法设计与分析 M. 北京:4Java编程思想第四版,Bruce Eckel著 陈昊鹏译,机械工业出版社,2012.115龙亚.图的连通性算法探讨J.毕节师范高等专科学校学报,2002 附录1:a.Graph .java:import java.util.*;pub

21、lic interface Graph /图的接口,包含图的操作 void intialGraph();/创建图 public boolean IsConnectedGraph();/检查是否为连通图 public void createGraph(Edge d);/根据边集组创建一个图createEdgeList();/由邻接矩阵生成边集列表 int vertices(); /返回图的定点数 int edges();/返回图的边数 void putEdge(Edge e);/填点边 void removeEdge(int i,int j);/删除边 boolean findEdge(int

22、i ,int j);/查找边 void output();/输出图 depthFirstSearch(int v);/深度优先遍历 void breakLoopBST();/删边获得最小生成树 public class Edge implements Comparable e.weight?1:(weight -1:0); Override public String toString() return (+fromvex+,+endvex+)+weight; /覆盖toString方法 a. AdjacencyGraphy.javaimport java.util.ArrayList;imp

23、ort java.util.Collections;import java.util.HashSet;import java.util.List;/import java.util.Random;import java.util.Scanner;public class AdjacencyGraphy implements Graph final int MaxValue = 1000;/一个不存在的边的权值 int n; /顶点数 int e; /边数 int a; /邻接矩阵 public AdjacencyGraphy(int n)/初始化 this.n = n; e = 0; a =

24、new intnn; for(int i = 0 ;i n ; i +) for(int j = 0 ; j j +) if(i=j) aij=0; else aij=MaxValue; public int getMaxValue()return MaxValue;public AdjacencyGraphy() intialGraph();/*实现接口中的方法*/public void intialGraph()System.out.print(请输入图的顶点数:);Scanner s = new Scanner(System.in);n=s.nextInt();a = new intnn;/Random random1 = new Random(100);/System.out.println(请输入图邻接矩阵(无边的权值为1000):for(int k

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1