zoukankan      html  css  js  c++  java
  • 递归

     

     什么是递归?


     它有这种特征。求解规模为N的问题时,设法将它分解成规模较小的问题。然后依据这些小问题方便的构造出大问题的解。当然程序必须有一个出口,当规模为1的时候,能直接的到解。


     小结:就是把问题层层分解,直到程序的出口处。


     注意事项

     1.递归应有终止的时候。也就是每个递归必须有一个出口,否则会无限递归出去。

     2.递归就是调用自身的方法。比如f(n)=n*f(n-1)


     裴波纳契数列


     先观察以下一组数字有何规律呢

     1、1、2、3、5、8、13、21、34……

     假设给你上面这些数字,预计可以非常快的写出后面的55、89等

     假设细心的话,就能够发现规律f1=1、f2=1、 f(n)=f(n-1)+f(n-2)(n>2)

     到此我们在返回去看递归的定义,就会发现。每个根问题都能够通过子问题来得到结果。所以终于呈现出这样一种现象,层层递归。


     DEMO

     class Fibonacci
        {
            static void Main(string[] args)
            {
      
                int result = fib(5);     
                Console.WriteLine(result);      
            }
    
    
            public static  int fib(int index)
            {
                //定义可以直接得到的值
                //也就是程序的出口
                if(index==1||index==2)
                {
                    return 1;
                }else
                {
                    //嵌套递归
                    return fib(index - 1) + fib(index - 2);
                }
            }
        }


     程序的分析流程图例如以下


     

      另一些求N的阶乘的问题,跟上面类似都是一类的套路。以下看一个经典的问题。


      汉塔诺问题

     


      看上面的图片要解决的问题是

      怎样把A上面的N个盘子借助B移动到C上。条件是


      1.一次仅仅可以移动一个盘子

      2.移动过程中大盘子永远不能放到小盘子上面


      看了这个问题。我们能够肢解一下。实现步骤例如以下

      1.先把A柱子上的前N-1个盘子从A借助C移动到B上

      2.将A柱子上的第N个盘子直接移动到C

      3.再将B柱子上的N-1个盘子借助A移到C上


      通过分析,我们发现上面的过程也是递归的,无论事N个还是N-1个盘子,实现的步骤都是上面的过程。

      class HuoNaTa
        {
            static void Main(string[] args)
            {
                //定义三个盘子
                char ch1 = 'A';
                char ch2 = 'B';
                char ch3 = 'C';
                move(5, ch1,ch2,ch3);
                     
            }
    
            
           /// <summary>
            /// //移动的过程
           /// </summary>
           /// <param name="num">盘子数目</param>
           /// <param name="A">A柱子</param>
           /// <param name="B">B柱子</param>
           /// <param name="C">C柱子</param>
            private static void move(int num,char A,char B,char C)
            {
                //假设是一个盘子
                     //直接将A柱子上的盘子从A移动到C
                if(num==1)
                {
                    Console.WriteLine("移动盘子1从" + A + "到" + C);
                }
                else
                {
                    //假设是多个盘子
                      //先将A柱子上的N-1个盘子借助C移到B
                      //直接将A柱子上的盘子从A移到C
                      //最后将B柱子上的N-1个盘子借助A移到C
                    move(num - 1, A, C, B);
                    Console.WriteLine("移动盘子" + num + "从" + A + "到" + C);
                    move(num - 1, B, A, C);
                }
            }
    
        }

      总结

      对于算法,确实刚上来理解不是特别的easy。可是全部的操作都须要亲身实践,包含每一步流程都须要认真的写下来,在写的过程中摸索规律。对于汉诺塔自己理解的也不是特别的深刻,可是可以从宏观上知道每一步的流程,然后通过递归来实现。也不知各位发现了木有,全部的递归在实现上都是有两步。一则定义出口,二则定义须要递归的地方。假设这么看的话,递归也就这么一回事。


      当然关于递归还有须要要学习的,有不正确的地方。多多指正!

    

    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    hrbustoj 2283 heap解题报告
    hrbustoj 2013 Play Game 2(博弈)
    hrbustoj 2130 一笔画(状态压缩)
    hrbustoj 1125 循环小数 II(小数变分数+极限思想)
    FZU 2170 花生的序列(动态规划)
    FZU 2168 防守阵地 I(前n项和的前n项和)
    FZU 2107 Hua Rong Dao(暴力回溯)
    FZU 2122 又见LKity(KMP+返回所有匹配位置)
    socket
    osi七层协议2
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4885037.html
Copyright © 2011-2022 走看看