欧拉回路

 

 这个权当做是自己的一个小小的总结。

    一笔画的问题从小就玩了,而且大多也是在小学玩得不亦乐乎!

    前天又看了看图论的东西,看到了欧拉回路,其实以前也遇到过如何输出一条欧拉回路(在存在的情况下),下面的程序不是我写的,只能说是花了较长的时间去看它了。

     设G为欧拉图,一般说来G中存在若干条欧拉回路,下面是求欧拉回路的Fleury算法:

    Fleury算法:
    (1)任取v0∈V(G),令P0=v0;
    (2)设Pi=v0e1v1e2...eivi已经行遍,按下面方法来从E(G)-{e1,e2,...,ei}中选
         取ei+1:
        (a)ei+1与vi想关联;
        (b)除非无别的边可供行遍,否则ei+1不应该为Gi=G-{e1,e2,...,ei}中的桥.
    (3)当(2)不能再进行时,算法停止。

    上面的红颜色字的字是网上的摘抄,在我看到之前不是我的东西。

    从上述算法中,可以看到,从给定的起始点开始,一次往P中添加节点和边(节点可重复)。在(2)中提到Pi=v0e1v1e2...eivi已经行遍,这是什么意思?什么叫已经行遍?仔细分析后发现,其实就是在采用如下的DFS时,无法向P中继续添加节点和边。

     void DFS(int dot)                      
    {
         V.top++;
         V.Ddian[V.top]=dot;

         for(int k=1;k<=nValue;k++)
             if(1==mapE[k][dot]&&k!=dot){          //先排除环的情况,待最后输出时加入 
                   mapE[k][dot]=0; 
                   mapE[dot][k]=0;
                   DvsMap(k);
                   break;
             }
    }
    此处的DFS并不是遍历图中的所有节点(当然也是有可能遍历到全部节点的),而是生成一个节点边的序列环。如下图所示,会生成序列:1,2,3,1,4,5,1 (起始点为节点1)  


图片

    此处的DFS不同于算法书上的DFS就在于,它没有标记节点是否访问过,而是把访问过的边给标记删除了。而且此DFS可以保证访问序列一定回到起始节点( 因为节点的度数是偶数),这就保证了,欧拉回路的正确性,即确保已经输出的一部分路径的确是欧拉回路的一部分。起始点与上一次最后一个输出地节点相连,如果此次遍历之后,该起始节点仍然能偶扩展,则继续扩展,否则按下面的规则输出,我们会发现,该起始节点和上一次最后输出地节点是相继输出的。
    访问到序列保存在栈中,此刻通过出栈操作即可输出欧拉回路的一部分,而输出的的条件是,节点必须无扩展能力了,亦即与该节点相连的边都已经被访问过,而通过栈保存依次访问的节点可以保证节点之间是相连的。在输出的过程中要记得出栈,而不仅仅是访问顶端节点。
     首先给出一个求欧拉回路的关键程序,然后分析其中的一些关键问题。
    while(栈不空)
    {
        if(顶端节点无扩展能力)
        {
          输出;
          出栈;
        } 
        else
        {
        出栈
        DFS(出栈前的节点);
        }   
    }
    上面是一部分伪代码,我想难以理解的地方就是在节点有扩展能力的时候,为什么要先进行出栈操作,却又依然传递出栈前的栈顶的值给DFS函数,而不是直接传递栈顶值给DFS,这个主要是因为在DFS函数中有一个入栈操作, 如果我们不进行出栈操作,那么当前的可扩展节点就会在栈中占用两个相邻的位置,即重复了。
    还有一个需要讨论的地方,由于DFS遍历的时间复杂度是O(n+e),为了节约时间需要判断图中是否有欧拉回路,如果没有就不用寻找,节省了时间。
     判断方法就是欧拉给的,判断所有节点的度数是否都为偶数 。

     //回溯法求解欧拉回路
    从某一点开始DFS,如果扩展某一个节点之后,所有点的边都已经被遍历,则停止。如果没有则继续扩展,在此分两种情况,1. 如果此节点无法扩展,则回溯(走错路了),2. 如果可以扩展则继续扩展。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值