递归简论

本文基于 Java 描述.

0. 定义

我们熟悉的大多数数学函数都是由一个简单公式来描述的。例如,我们可以利用公式:

C=5(F-32)/9  

将华氏温度转换成摄氏温度。

在这里插入图片描述
有的时候,数学函数以不太标准的形式来定义,例如,我们可以在非负整数集上定义
一个函数f,它满足:

f(0) =0,且f(x) = 2f(x-1)+x^2.

然后从这个定义我们可以看到

f(1)=2*f(0)+1=1
f(2)=2*f(1)+4=6
f(3)=2*f(2)+9=21
f(4)=2*f(3)+16=58

当一个函数用它自己来定义时就称为是递归(recursive)。

1. 举例

public   static  int f( int x) {
    if ( x==0) //递归退出条件;基准情况
        return 0;//基准情况
    else 
       return 2*f(x-1) + x*x;//执行递归调用

}

第2行和第3行处理基准情况 ,即此时函数的值可以直接算出而不用求助递归。正如:

f(x) = 2*f(x-1)+x^2

正如若没有f(0)=0这个事实,那么此f(x)函数在数学上没有意义一样,Java的递归方法若无基准情况也是毫无意义的。

递归可能被混淆的概念:一个常见的问题是:它是否就是循环推理?

答案是: 虽然我们定义一个方法用的是这个方法本身,但是我们并没有用方法本身定义该方法的一个
特定的实例。换句话说,通过使用f(5)来得到f(5)的值才是循环的。通过使用f(4)来得到f(5)的值
不是循环的。当然,除非 f(4)的求值又要用到对f(5)的计算。

2. 无终止的递归方法

public static int bad ( int n) {

    if ( n == 0)
        return 0;
    else
        return bad( n/3+1) + n-1;

比如你要输入一个n=5, 代码跑一下:

return bad( 5/3+1) + 5-1  -->   return bad(2)+4

然后就要找bad(2)

return bad(2/3+1) + 2-1  --> return bad(1)+1

然后就要找bad(1)

return bad(1) +1-1   --> return bad(1)+0

由于这个bad(1)在代码里面没有定义,所以计算机会反复调用bad(1)以期望解出它的值,然后内存被占满,程序崩溃;

3. 总结

在这里插入图片描述

以上讨论导致递归的前两个基本法则:

1. 基准情形(base case),必须总要有某些基准的情形,它们不用递归就能求解

2. 不断推进(marking progress),对于那些要递归求解的情形,递归调用总是能够朝着一个基准情形推进

本文OVER! 感谢阅读。

本文参考自《Data Structures and Algorithm Analysis in Java》.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值