递归与分治策略

来源:互联网 发布:西裤材质 知乎 编辑:程序博客网 时间:2024/05/01 07:03

         分治:字面上理解就是分而治之,就是把一个复杂的问题分成两个或多个相同或相似的子问题,再把子问题分成更小的子问题...知道最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。

         递归:直接或间接地调用自身的算法称为递归算法。递归的两个要素:结束条件(边界条件)和递归方程,具备这两个条件,才能在有限次计算后得出结果。

       递归算法的执行效率通常较差,因此需要将递归算法转换为非递归算法。有两种方式:直接转化法和间接转换法。

       1,直接转换法:

              直接转换法需要使用一些变量保存中间结果。直接转换法通常用来消除尾递归和单向递归,将递归结构用循环结构来替代。

              尾递归是指在递归算法中,递归调用语句只有一个,而且处在算法的最后,例如阶乘的算法:

              long  fact(int n)

             {

                       if(n==0) return 1;

                       else  return n*fact(n-1);

              }

             比如n=3,即return 3*fact(3-1),继续分解:return 3*2*fact(2-1),继续return 3*2*1.

              当递归调用返回时,是返回到上一层递归调用的下一条语句,而这个返回位置正好是算法的结束处,所以,不必要利用栈来保存返回信息。对于尾递归形式的递归算法,可以利用循环结构来替代。所以可以写成下面的非递归算法:

             long fact(int i)

           {

                  int s=1;

                  for(int i=1;i<=n;i++)

                  s=s*i;         //用s保存中间结果

                 return s;

           }

           单向递归是指递归算法中虽然有多处递归调用语句,但各个递归调用语句的参数之间没有关系,并且这些递归调用语句都处在递归算法的最后。显然,尾递归是单向递归的特例。比如求斐波那契数列的递归算法如下:

           int  f(int n)

          {

              if(n==1 || n==0) return 1;

              else  return f(n-1)+f(n-2);       //两个递归调用语句的参数不互相依赖,他们之间没有关系。

           }

           对于单向递归,可以设置一些变量保存中间结果,将递归结构用循环结构来替代。比如:

            int  f(int n)

            {

                int i,s;

                int s1=1,s2=1;

                for(i=3;i<=n;i++)

                {

                       s=s1+s2;

                      s2=s1;                 //保存f(n-2)的值

                      s1=s;                  //保存f(n-1)的值

                 }

                 return s;

            }

         2,间接转换法

               该方法使用栈保存中间结果,一般需要根据递归函数在执行过程中栈的变化得到。一般过程如下:

               初始状态s0进栈。

                while(栈不为空)

                {

                       退栈,将栈顶元素赋给s;

                        if(s是要找的结果)     返回;

                       else

                       {

                                 寻找到s的相关状态s1;

                                 将s1进栈

                          }

                   }

                  间接转化法在数据结构中有较多实例,如二叉树遍历算法的非递归实现、图的深度优化遍历算法的非递归实现等等。

          因此,对求解某些问题时,我们希望用递归算法分析问题,用非递归算法具体求解问题。

          递归算法转换为非递归算法有三种基本方法:

             1,通过分析,跳过分解过程,直接用循环结构的算法实现求值过程。

             2,自己用栈模拟系统的运行时栈,通过分析只保存必须保存的信息,从而用非递归算法替代递归算法。

             3,利用栈保存参数,由于栈的后进先出特性吻合递归算法的执行过程,因而可以用非递归算法替代递归算法。


           

原创粉丝点击