递归简论
什么是递归?
当一个函数用它自己来定义时称之为递归,但并不是所有的数学递归函数都是正确地或有效地用C语言来递归模拟实现。
递归的基本原则
我们通过Fibonacci代码(实际编程中并不建议使用递归来求解Fibonacci数列,原因后面将会提到)来解释递归的基本原则
int Fibonacci( int n)
{
if (n==1 || n==2)
return 1;
else
{
return Fibonacci(n-2)+Fibonacci(n-1);
}
}
-
递归具有基准条件:当我们使用递归时,首先是找到递归结束的基准条件,即不用递归就可以求解。例如上述代码中的当
n=1 or n=2时,不用递归就可以求解。 -
递归需要不断地向基准条件靠近:通过观察上述代码,这个以原则不难理解,若是我们没有向基准条件靠近,那我们的递归就很难结束,这里需要注意三种情况:
- 第一种情况是循环调用。例如求解F(6)需要调用F(5), F(5)调用F(4),然而F(4)却需要调用F(6),这里调用情况出现了一个环,因此程序会在这个环中循环而无法靠近基准条件。
- 第二种情况是不能靠近基准条件。这种情况我们用下面的代码说明,在下面代码中当
n!=0时,该递归无论循环多久都达不到基准条件,这只是情况之一,由于计算机的运算规则与我们平时熟知的数学运算规则的一些差异,该类情况会在我们不经意间发生,较为隐蔽,值得我们注意。int Endless(int n) { if ( n==0 ) return 0; else return Endless(n/3+1); } ```
- 第三种情况是初始值n 的取值问题,例如Fibonacci代码中
当n=-1,该递归会逐渐远离基准条件,当然这种简单的问题一眼看穿,很少人去跳坑。
-
所有的递归调用都能运行。这里就涉及到上面需要注意的第三点情况。
-
在求解一个问题的同一实例时,不要再不同的递归中做同样的工作。在上文中我们用到递归的方法求取Fibonacci数列,看似一切都很合理,但是并不符合第四点,我们思考一下,当我们求取Fibonacci(5) 时,我们需要求取Fibonacci(4) & Fibonacci(3),在求取Fibonacci(4)时,需要求取Fibonacci(3) & Fibonacci(2), 相信看到这里,你已经明白为什么我说实际编程中,我们不建议使用递归的方法求取Fibonacci数列,因为在求取Fibonacci(5) 时,我们重复计算了Fibonacci(3) ,这种多余的计算时没必要的,尤其是在当N过大的情况下,其额外计算量将非常庞大。

被折叠的 条评论
为什么被折叠?



