zoukankan      html  css  js  c++  java
  • 递归转非递归几个实例

    递归是程序设计中很重要的技巧,简单易于实现;但递归程序效率较之非递归低得多,递归函数要直接或间接的调用自身,系统栈要频繁操作,时间空间消耗很大。在要求高效的很多场合需要将递归程序改写成非递归程序,由于疏于梳理这方面的知识点,感觉对于有些递归结构有些力不从心,于是有意识的学习了一下,感觉好了很多。

    关于递归程序转非递归程序,基本通用方法是用自定义栈结构模拟递归过程,这种方法就是万金油,几乎所有递归都适用,之所以说几乎,主要考虑是暂没有见过用栈解决不了的,但碍于怕自己视野狭窄所以说几乎。如果从系统角度看递归,栈机制模拟能解决所有问题。其次,对于具体问题,可以有其他方法,直接迭代、动态规划什么的,像斐波那契数列就可以用直接迭代写成非递归的;动态规划也是直接迭代的一种,但需要转换思想,提取问题的最优子结构,像数塔问题、归并排序等都属于这类。关于这类,就不说了,这得视具体题目而定,发现问题的结构,寻找状态转移方程。

    一般的还是得用栈模拟,这里主要谈谈栈模拟。以下所有代码重在说明算法,没有考虑爆栈、溢出等涉及程序的鲁棒性因素,还请谅解。

    一、汉诺塔问题

    汉诺塔是根据一个传说形成的一个问题:有三根杆子A,B,C。A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至C杆:
    每次只能移动一个圆盘;
    大盘不能叠在小盘上面。
    提示:可将圆盘临时置于B杆,也可将从A杆移出的圆盘重新移回A杆,但都必须遵循上述两条规则。问:如何移?最少要移动多少次?(问题描述转自维基百科)

    具体解法思想为先将A杆上面的n-1个借助C杆移到B杆,然后将A杆最低一根直接移到C,再将n-1根借助A杆从B移到C。上面隐含着递归思想将问题逐渐减小最后递推到原问题。

    此时注意栈中元素不是单一的,要保留当前状态,可以用结构体,也可以多维数组,下面给出结构体做法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    #include<IOSTREAM>
    using namespace std;
      
    const int MAXN=10000;
    int m_Move=0;
      
    /**********************************************
    *汉诺塔递归解法
    ***********************************************/
    void recurHanoi(char from,char use,char to,int n)
    {
        if(0==n)
            return ;
        recurHanoi(from,to,use,n-1);
        cout<<N<<"从"<<FROM<<"移到"<<TO<<ENDL; while(top from,use,to,number,id; char myStack[++top]="now;" now.from="'A';now.use='B';now.to='C';now.number=n;now.id=n;" m_Move="0;" top="0;" int now; Node myStack[MAXN]; cout<<?********非递归算法*********?<<endl; { n) notRecurHanoi(int void } cout<<now.id<<?从?<<now.from<<?移到?<<now.to<<endl; ++m_Move; now) print(Node }; to; use; from; id; number; struct *********************************************** *汉诺塔非递归解法 ********************************************** cout<<?**************************?<<endl; cout<<?总共移动?<<m_Move<<?次?<<endl; recurHanoi(&#39;A&#39;,&#39;B&#39;,&#39;C&#39;,n); cout<<?*********递归算法**********?<<endl; recurHanoi(int recurHanoi(use,from,to,n-1);>0)
         {
             if(1==myStack[top].number)
            {
                print(myStack[top]);
                --top;
             }
             else 
             {
                 from=myStack[top].from;use=myStack[top].use;to=myStack[top].to;number=myStack[top].number;id=myStack[top].id;
                 --top;
      
                 now.from=use;now.use=from;now.to=to;now.number=number-1;now.id=id-1;
                 myStack[++top]=now;
      
                 now.from=from;now.use=use;now.to=to;now.number=1;now.id=id;
                 myStack[++top]=now;
      
                 now.from=from;now.use=to;now.to=use;now.number=number-1;now.id=id-1;
                 myStack[++top]=now;     
             }
         }
         cout<<"总共移动"<<M_MOVE<<"次"<<ENDL; int { } cout<<?**************************?<<endl; while(cin n; main()>>n)
        {
            recurHanoi(n);
            notRecurHanoi(n);
        }
        return 0;
    }


    二、组合数

    C(n,m)=C(n-1,m)+C(n-1,m-1) n>m

    C(n,m)=1 n=m或m=0

    此问题的递归形式比较简单,非递归形式得深入理解过程,直接栈模拟,注意进出栈的时机,在此不多说可以看看拙劣的代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    #include<IOSTREAM>
    using namespace std;
      
    const int MAXN=100;
      
    int recurCombineCount(int n,int m)
    {
        if(0==m||n==m)return 1;
        else return recurCombineCount(n-1,m)+recurCombineCount(n-1,m-1);
    }
      
    int notRecurCombineCount(int n,int m)
    {
        int stack[MAXN][3];
        int top=0;
        ++top;
        stack[top][0]=n;stack[top][1]=m;stack[top][2]=0;
        do
        {
            if(0==stack[top][2])//计算C(n-1,m)
            {
                ++top;
                stack[top][0]=stack[top-1][0]-1;stack[top][1]=stack[top-1][1];stack[top][2]=0;
                if(stack[top][0]==stack[top][1]||0==stack[top][1])
                    stack[top][2]=1;
            }
            if(top>=2&&stack[top][2]>0)//计算C(n-1,m-1)
            {
                ++top;
                stack[top][0]=stack[top-2][0]-1;stack[top][1]=stack[top-2][1]-1;stack[top][2]=0;
                if(stack[top][0]==stack[top][1]||0==stack[top][1])
                    stack[top][2]=1;
            }
            while(top>=3&&stack[top-1][2]>0&&stack[top][2]>0)//计算C(n,m)
            //注意此处这样有错://if(top>=3&&stack[top-1][2]>0&&stack[top][2]>0)
            {
                stack[top-2][2]=stack[top-1][2]+stack[top][2];
                top-=2;
            }
        }while(top>1);
        return stack[top][2];
    }
      
    int main()
    {
        int n,m;
        while(cin>>n>>m)
        {
            cout<<"************递归算法**************"<<ENDL; } pre < 0; return cout<<?*********************************?<<endl; cout<<?结果为:?<<notRecurCombineCount(n,m)<<endl; cout<<?***********非递归算法*************?<<endl; cout<<?结果为:?<<recurCombineCount(n,m)<<endl;><BR>
       
    <P></P>
    <P>         这几天持续更行中!<BR>
    </P>
    <P>      由于时间有限,疏于测试,如有不足或错误,欢迎斧正!<BR>
    </P>
    <P><BR>
    </P>
    <P><BR>
    </P>
    <P><BR>
    </P>          
  • 相关阅读:
    严重: Parse error in application web.xml file at jndi:/localhost/ipws/WEBINF/web.xml java.lang.NoSuchMethodException: org.apache.catalina.deploy.WebXml
    Failed to install .apk on device 'emulator5554': timeout解决方法
    java.lang.NoClassDefFoundError:org.jsoup.Jsoup
    Conversion to Dalvik format failed: Unable to execute dex:解决方法
    apache Digest: generating secret for digest authentication ...
    Description Resource Path Location Type Project has no default.properties file! Edit the project properties to set one.
    android service随机自启动
    MVC3 安装部署
    EF 4.3 CodeBased 数据迁移演练
    SQL Server 2008开启sa账户
  • 原文地址:https://www.cnblogs.com/firstdream/p/5534220.html
Copyright © 2011-2022 走看看