首页 > 代码库 > 递归的理解

递归的理解

1.什么是递归?

递归就是直接或间接的调用自己

2.怎么对一个问题建模并转化为递归的形式?

这个问题就大了,首先建模这个东西已经超出了程序员的范畴,那其实是数学的一部分。

3.那么是不是一点办法都没有呢

经过书上的讲解,上课老师的讲解,视频讲解,网上资料的讲解,现在对待递归的本质有了更深入的认识了

对于一些简单地问题,我们如何建模!找几个例子,然后继续总结!

    例1:,就是阶乘,如何建模使用递归!

当n=1时,1的阶乘是1;

当n=2时,2的阶乘是1*2;

当n=3时,3的阶乘是1*2*3;

所以函数表达式可以写成         n!=n*(n-1)!(n>1)     n=1时,1!=1(这个有些书上讲这个是边界条件,或者是出口)

diGui(int n)

{

if(n==1)

return 1;

diGui(n-1)*n;

}

例2:斐波那契数列也是这个样子的!(找到其边界条件,2个,f1=1,f2=1)

例3:汉诺塔问题?(这里我就不再叙述它的规则了,直接建模)

有3个柱子分别是ABC,盘子由小到大分别用1,2,3表示

当盘子只有1个的时候,直接从盘子A移动到盘子C

当盘子只有2个的时候,先是将盘子1,通过C,移动到B

                     然后将盘子2,直接移动到C

                     最后将盘子1,通过盘子移动到C上

当盘子只有3个的时候,先将1.2盘子,通过C,移动到B(和当n==2的情况一样)

                     然后将盘子3,直接移动到C

                     最后将盘子1,2,移动到到C上

当有n个盘子的时候,现将n-1个盘子,通过C,移动到B

                   然后将盘子n,直接移动到C

   最后将盘子n-1,通过A,移动到到C上

表达式:hannuota(int n,char a,char b,char c)

{

if(n==1)

move(a,c);

hannuota(n-1,a,c,b)

move(n,a,b,c)

hannuota(n-1,c,a,b);

}

总结:建模都是从当n=1时候,开始的总结,n=2时候是什么样子,n=3,有将会是多少,

      另外观察当n=3,是否是在2的基础上运行的(是看他们的思想),看3模型,在2的思想和2在1的思想上是否是匹配的,如果匹配可以使用递归,如果不匹配那不符合递归,递归和面向对象一样都是一种模型,就看你匹不匹配。如果匹配就可以用递归(模型匹配)

我在举个二叉树的先序遍历的例子。

3个节点的时候,头结点,左结点,右结点。(n=1)

7个节点的时候,头结点,然后是左结点全部遍历完之后,然后是右结点,而不是在3个节点基础上继续遍历剩余的结点,难道是否不匹配,不是,其实是已经分叉了,递归它的里面已经有多分支递归了。从左子树开始的时候,开始类似于3个节点的时候,这边是模式匹配,这已经是多分支了,同样右结点开始的时候也是3个节点的类似,这又匹配,所以多分支了。递归只要设计出两部,后面的就基本不用看了,只要校验一下,看看对不对,证明是很难证明的,有点类似于数学归纳法。

//以上自底向上的逻辑思考方式:


//下面通过自顶向下的逻辑思考方式:

如何遍历二叉树:试想下如果这颗二叉树非常复杂,西遍历头部,头部遍历完了,在遍历左边,左边遍历完了在遍历右边。发现左边又很复杂,先遍历左边的头,在遍历左边的左边,在遍历右边的右边。

递归算法如何思考编写?

      函数名

{

遍历头

遍历左边

{

先遍历头

遍历左边头              --->这不应该还是函数名吗?//执行流程思想全是一样的。

遍历右边头

}

遍历右边

{

遍历头

遍历左边              --->这不应该还是函数名吗?//执行流程思想全是一样的。

遍历右边

}

}

关于递归的写法,总之要有个出口。也就是边界条件。

第二个就是设计递归函数表达式。


本文出自 “简答生活” 博客,转载请与作者联系!

递归的理解