zoukankan      html  css  js  c++  java
  • 递归的正确切入方法

    一、递归的定义

    定义: 当函数直接或者间接调用自己时,则发生了递归。

    二、理解递归

    先举个递归在阶乘中的例子:阶乘的定义: “一个正整数的阶乘是所有小于或等于该数的正整数的积,并且0的阶乘为1。”

    以下是C++的实现:

    int factorial(int n)
    {
    	if(n <= 1)
    		return 0;
    	else
    		return n * factorial(n-1);
    	
    }
    

     分析:我们很容易判断当n = 某个较小数值时这个阶乘的递归计算是否是正确。比如当n = 4时, 那么factoria(4)等于4 * factoria(3), 而factoria(3)等于3 * factoria(2)factoria(2)等于2 * factoria(1),等于2 * 1,所以factoria(4)等于4 * 3 * 2 * 1。


    反思:这种分析已经有点门路了,可是怎么拓展到一般情况呢?

    Paul Graham提到一种方法, 给我很大启发, 该方法如下:

    1. 当n=0,1的时候,结果正确;
    2. 假设函数对于n是正确的, 函数对n+1结果也正确。
    3. 如果这两点是成立的,我们知道这个函数对于所有可能的n都是正确的。

    这种方法很像数学归纳法, 也是递归正确的思考方式, 事实上, 阶乘的递归表达方式就是1! = 1,n! = (n-1)! × n,当程序实现符合算法描述的时候, 程序自然对了, 假如还不对, 那是算法本身错了…… 相对来说,n,n+1的情况为通用情况, 虽然比较复杂, 但是还能理解, 最重要的, 也是最容易被新手忽略的问题在于第1点, 也就是基本用例(base case)要对. 比如, 上例中, 我们去掉if(n<=1)的判断后, 代码会进入死循环, 永远不会结束。

     

    三、寻找问题的递归算法

     

    在解题时,想运用递归却无从下手?

    你只需要做两件事情:

    1. 示范如何解决问题的一般情况, 通过将问题切分成有限小并更小的子问题;
    2. 示范如何通过有限的步骤,来解决最小的问题(基本用例);
    3. 因为递归每次都将问题变得更小,而一个有限的问题终究会被解决的,而最小的问题仅需几个有限的步骤就能解决。

    四、实战运用

     

    汉诺塔问题:有三根杆子A,B,C。A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至C杆:1.每次只能移动一个圆盘;2.大盘不能叠在小盘上面。

     

    如何使用递归?

    一般情况:
    当有N个圆盘在A上,我们已经找到办法将其移到C杆上了,我们怎么移动N+1个圆盘到C杆上呢? 很简单, 我们首先用将N个圆盘移动到C上的方法将N个圆盘都移动到B上, 然后再把第N+1个圆盘(最后一个)移动到C上, 再用同样的方法将在B杆上的N个圆盘移动到C上。问题解决。

    基本用例:
    当有1个圆盘在A上,我们直接把圆盘移动到C上即可。

     

    C++代码:

     1 // 汉诺塔
     2 # include  <stdio.h>
     3 void hanoi ( int n, char a,  char b,  char c )         //这里代表将a柱子上的盘子借助b柱子移动到c柱子
     4   {  if  (1 == n)                                          //如果是一个盘子直接将a柱子上的盘子移动到c
     5          {
     6             printf("%c-->%c
    ",a,c);
     7           }
     8        else
     9            {
    10              hanoi ( n-1,  a,  c,  b ) ;                  //将a柱子上n-1个盘子借助c柱子,移动到b柱子
    11              printf("%c-->%c
    ",a , c) ;               //再直接将a柱子上的最后一个盘子移动到c
    12              hanoi ( n-1,  b,  a,  c ) ;                  //然后将b柱子上的n-1个盘子借助a移动到c
    13           }
    14   }
    15 int main ()
    16   {  int  n ;
    17       printf( "Input the number of diskes:") ;
    18       scanf("%d",&n) ;
    19       hanoi ( n,  'A' ,  'B' , 'C' ) ;
    20       return 0;
    21   }

     

  • 相关阅读:
    遗传算法(Genetic Algorithm, GA)及MATLAB实现
    CCF CSP 201809-2 买菜
    PAT (Basic Level) Practice (中文)1008 数组元素循环右移问题 (20 分)
    PAT (Basic Level) Practice (中文)1006 换个格式输出整数 (15 分)
    PAT (Basic Level) Practice (中文)1004 成绩排名 (20 分)
    PAT (Basic Level) Practice (中文)1002 写出这个数 (20 分)
    PAT (Advanced Level) Practice 1001 A+B Format (20 分)
    BP神经网络(原理及MATLAB实现)
    问题 1676: 算法2-8~2-11:链表的基本操作
    问题 1744: 畅通工程 (并查集)
  • 原文地址:https://www.cnblogs.com/xzxl/p/7223145.html
Copyright © 2011-2022 走看看