最小生成树和最短路径.docVIP

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
最小生成树和最短路径

最小生成树and最短路径 无独有偶,在两个学期的期末中两门不同的科目《离散数学》和《数据结构》中都谈到了图及其衍生的最小生成树、最短路径问题,并给出了相应的算法——克鲁斯卡尔、普林、迪杰斯特拉、沃舍尔算法。这无疑是释放了一个很大的信号——这些内容很重要。由于之前学《离散数学》时只要求在思想上理解,并没要求程序实现,所以学起来也挺吃力的。而现在来到了《数据结构》的课程上,我觉得还是有必要写写理解与体会,好让以后用起来没那么难。 最小生成树(Minimum Spanning Tree,MST ) 一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。即是在原图上删除边,直到剩余n-1条边,保证n个结点连通且边的权值加起来最小。 简单图示: 21 1 2 1 21 1 2 1 3 2 MST 2 5 4343 4 3 4 3 4 4 克鲁斯卡尔(Kruskal)算法 克鲁斯卡尔算法从边的角度来解决问题,即在剩下的所有未选取的边中,找最小边,如果和已选取的边构成回路,则放弃,选取次小边。然而,图的存贮结构采用边集数组,且权值相等的边在数组中排列次序可以是任意的,该方法对于边数相对比较多的图不是很实用,浪费时间。可以说克鲁斯卡尔算法是很直观的算法,适合人的直观思考方式,但是因为上面论述的缘故,克鲁斯卡尔算法比较适用在稀疏图(边的数目不是很多的图)上。 边集数组: 从图变为程序需要的数据,需要采用合适的数据结构。由算法的核心思想上看,我们需要存储的数据为边,而边的要素包括三点:连接的两个结点、边的权值。然而边并不需要具有什么操作来改变自身或者做些什么,所以用struct来自定义就合适不过了。 struct edge{ int node_1; int node_2; int value ; }; 另外,文中提及了最小边、次小边,这就暗示了应该对所有的边进行排序(sort)。 比较函数应以value作衡量。 bool cmp(edge a , edge b) { ??? return a.value b.value ; } 现在剩余最后的问题——回路的避免。其实这个也很容易避免,我们可以定义一个数组used[max],它记录了每一个结点是否被应用的情况,当要加入的一条边中used[a.node_1]和 used[a.node_2]都已被应用,那么加入的这条边必然造成回路,否则不会。若造成回路,则舍弃这条边,转而观察加入次小边。 排序后的情况 edge数组 node_1 node_2 value 0 1 2 1 1 2 4 2 2 2 4 3 3 3 4 4 4 2 3 5 用红线将舍弃的边删除后,剩余的就成为了最小生成树了。 时间复杂度 若e表示图的边数,那么,排序过程将有O(eloge),生成过程则是O(e),故总的来说,时间复杂度为O(eloge)。 普林(Prim)算法 克鲁斯卡尔算法以边为出发点,相应地,普林算法则以点为出发点。从指定顶点开始将它加入集合中,然后将集合内的顶点与集合外的顶点所构成的所有边中选取权值最小的一条边作为生成树的边,并将集合外的那个顶点加入到集合中,表示该顶点已连通。再用集合内的顶点与集合外的顶点构成的边中找最小的边,并将相应的顶点加入集合中。如此下去直到全部顶点都加入到集合中,即得最小生成树。以点作为出发点很好地解决了克鲁斯卡尔算法解决边数很多的图的可怕时间复杂度的问题。边数不是制约普林算法的因素,结点才是。 普林算法的简单演算步骤: (1)初始化集合A(),表示没有点以加入到生成结点中,初始化集合B,使B包含所有结点; (2)从B中选择一个点作为始加入到A中并从B中剔除; (3)选择A中所有的点中能到达B的最小权值边,将这条边的另一个点加入到A中并从B中剔除; (4)重复(3)操作直至B为NULL,则为最小生成树。 邻接矩阵 如果说克鲁斯卡尔算法使用自定义的边集数组存储图是直观的,那么普林算法采用自定义的点集数组也是合适的?如果以某一点作为单独的数据结构,那么这一数据结构应当包含有与这个点有关的边的所有信息——权值和对应点。但事前我们并不知道这个图的点的最大度数为多少,带着这种未知来定义struct是危险的,所以我们应当采用邻接矩阵——一个存放顶点间关系(边或弧)的数据的二维矩阵,即有一个二维矩阵data,data[a][b]=c表示a结点和b结点有一条长为c的边,相应地,data[b][a]=c。当a,b之间没有边的时候,应当使data[a][b] = INF(INF表示无穷)。 集

文档评论(0)

f8r9t5c + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

版权声明书
用户编号:8000054077000003

1亿VIP精品文档

相关文档