zoukankan      html  css  js  c++  java
  • 图--生成树和最小生成树.RP

    树(自由树)、无序树和有根树

         自由树就是一个无回路的连通图(没有确定根)(在自由树中选定一顶点做根,则成为一棵通常的树)。
         从根开始,为每个顶点(在树中通常称作结点)的孩子规定从左到右的次序,则它就成为一棵有序树
         在图的应用中,我们常常需要求给定图的一个子图,使该子图是一棵树。

    生成树

    1、生成树

         如果连通图G的一个子图是一棵包含G的所有顶点的树,则该子图称为G的生成树(SpanningTree)。
         生成树是连通图的包含图中的所有顶点的极小连通子图。
         图的生成树不惟一。从不同的顶点出发进行遍历,可以得到不同的生成树。

    2、深度优先生成树和广度优先生成树
    (1)生成树的求解方法
         设图G=(V,E)是一个具有n个顶点的连通图。则从G的任一顶点(源点)出发,作一次深度优先搜索(广度优先搜索),搜索到的n个顶点和搜索过程中从一个已访问过的顶点vi搜索到一个未曾访问过的邻接点vj,所经过的边(vi,vj)(共n-1条)组成的极小连通子图就是生成树。(源点是生成树的根)
         通常,由深度优先搜索得到的生成树称为深度优先生成树,简称为DFS生成树;由广度优先搜索得到的生成树称为广度优先生成树,简称为BPS生成树。
      
    (2)求DFS生成树和BFS生成树算法
        只要在DFS(或DFSM)算法的if语句中,在递归调用语句之前加入适当生成边(vi,vj)的操作(如将该边输出或保存),即可得到求DFS生成树的算法。
        在BFS(或BFSM)算法的if语句中,加入生成树边(vi,vj)的操作,可得到求BFS生成树的算法。【参见练习】
      注意:
        ①图的广度优先生成树的树高不会超过该图其它生成树的高度
        ②图的生成树不惟一,从不同的顶点出发进行遍历,可以得到不同的生成树。

    3、生成树的通用定义
        若从图的某顶点出发,可以系统地访问到图中所有顶点,则遍历时经过的边和图的所有顶点所构成的子图,称作该图的生成树。(此定义不仅仅适用于无向图,对有向图同样适用。)
    (1)若G是强连通的有向图,则从其中任一顶点v出发,都可以访问遍G中的所有顶点,从而得到以v为根的生成树。
    (2)若G是有根的有向图,设根为v,则从根v出发可以完成对G的遍历,得到G的以v为根的生成树。
    (3)若G是非连通的无向图,则要若干次从外部调用DFS(或BFS)算法,才能完成对G的遍历。每一次外部调用,只能访问到G的一个连通分量的顶点集,这些顶点和遍历时所经过的边构成了该连通分量的一棵DFS(或BPS)生成树。G的各个连通分量的DFS(或BFS)生成树组成了G的DFS(或BFS)生成森林。
    (4)若G是非强连通的有向图,且源点又不是有向图的根,则遍历时一般也只能得到该有向图的生成森林。

    5、普里姆(Prim)算法
    (1)算法思想
         T=(U,TE)是存放MST的集合。
      ①T的初值是({r},¢)
        即最小生成树初始时只有一个红点r,没有红边。
      ②T经过n-1次如下步骤操作,最后得到一棵含n个顶点,n-1条边的最小生成树
         ⒈选择紫边集中一条轻边并扩充进T
      ⒉将轻边连接的蓝点改红点
      ⒊将轻边改红边
         ⒋修改紫边集

    (2)较小紫边集的构造
         若当前形成的T中有k个顶点,|U|=k,|V-u|=n-k,故可能的紫边数目是k(n-k)。从如此大的紫边集中选择轻边是低效的。因此,必须构造较小的紫边集。
         对于每个蓝点v ∈V-U,从v到各红点的紫边中,只有最短的那一条才有可能是轻边。因此,只须保留所有n-k个蓝点所关联的最短紫边作为轻边的候选集即可。

    (3)候选紫边集合的修改
         当把轻边(u,v)扩充到T时,因为v由蓝变红,故对每个剩余的蓝点j,边(v,j)就由非紫边变为紫边,这条新紫边的长度可能小于蓝点j原来所关联的最短紫边的长度。因此,用长度更小的新紫边取代那些原有的最短紫边。

    (4)Prim算法的伪代码描述
     PrimMST(G,T,r){
      //求图G的以r为根的MST,结果放在T=(U,TE)中
        InitCandidateSet(…);//初始化:设置初始的轻边候选集,并置T=({r},¢)
        for(k=0;k<n-1;k++){ //求T的n-1条树边
            (u,v)=SelectLiShtEdge(…);//选取轻边(u,v);
             T←T∪{(u,v)};//扩充T,即(u,v)涂红加入TE,蓝点v并人红点集U
            ModifyCandidateSet(…); //根据新红点v调整候选轻边集
          } 
       }

    (5) 算法的执行过程
         用PRIM算法得到最小生成树的过程【参见动画演示


      注意:
         若候选轻边集中的轻边不止一条,可任选其中的一条扩充到T中。
         连通网的最小生成树不一定是惟一的,但它们的权相等。
         
    (6)算法特点
         该算法的特点是当前形成的集合T始终是一棵树。将T中U和TE分别看作红点和红边集,V-U看作蓝点集。算法的每一步均是在连接红、蓝点集的紫边中选择一条轻边扩充进T中。MST性质保证了此边是安全的。T从任意的根r开始,并逐渐生长直至U=V,即T包含了 C中所有的顶点为止。MST性质确保此时的T是G的一棵MST。因为每次添加的边是使树中的权尽可能小,因此这是一种"贪心"的策略。
    (7)算法分析
         该算法的时间复杂度为O(n2)。与图中边数无关,该算法适合于稠密图。

    (1)算法思想
      ①T的初始状态
           只有n个顶点而无边的森林T=(V,¢ )
      ②按边长递增的顺序选择E中的n-1安全边(u,v)并加入T,生成MST
    注意:
         安全边指两个端点分别是森林T里两棵树中的顶点的边。加入安全边,可将森林中的两棵树连接成一棵更大的树
         因为每一次添加到T中的边均是当前权值最小的安全边,MST性质也能保证最终的T是一棵最小生成树。

    (2)算法特点
         该算法的特点是:当前形成的集合T除最后的结果外,始终是一个森林。

    (3)Kruskal算法的抽象描述
      KruskalMST(G){//求连通网G的一棵MST
         T=(V,¢); //初始化,T是只含n个顶点不包含边的森林
        依权值的递增序对E(G)中的边排序,并设结果在E[0..e-1]中
        for(i=0;i<e;i++) { //e为图中边总数
            取E[0..e-1)中的第i条边(u,v);
             if u和v分别属于T中两棵不同的树then
                T=T∪{(u,v)};//(u,v)是安全边,将其加入T中
             if T已是一棵生成树then
          ``         return T;
            }//endfor
           return T;
       } 

    (4)用Kruskal算法构造最小生成树的过程
         用Kruskal算法构造最小生成树的过程【参见动画演示


    (5)算法分析
         该算法的时间复杂度为O(elge)。
        Kruskal算法的时间主要取决于边数。它较适合于稀疏图。

    文自:http://blog.csdn.net/heavenboya/article/details/6654778

  • 相关阅读:
    多态的详解
    Java继承详解
    static关键字特点
    数组(相关知识的整理)
    杨辉三角(用for循环)
    Jmeter接口测试案例实践(一)
    组合测试方法:配对测试实践
    用例设计方法:判定表驱动法实践
    sso系统登录以及jsonp原理
    单点登录--sso系统
  • 原文地址:https://www.cnblogs.com/Leroscox/p/6143713.html
Copyright © 2011-2022 走看看