一、什么是递归?
递归的本质就是函数的自我调用,就是自己调用自己。
众所周知,递归是一种解决问题强有力的技巧。在描述有些问题时有不可替代的优势,但滥用递归很可能造成资源的巨大开销!
二、递归函数调用涉及哪些运行时开销?
<1>、参数必须压到堆栈
<2>、函数内部定义的局部变量的值也要压栈保存
<3>、函数的执行状态(寄存器的值)也要压栈保存
当递归函数的每次调用返回时,上述这些操作都必须还原,恢复成原来的样子。
三、通过求斐波那契数问题来观察递归的另一种开销--大量的冗余操作。
源代码实现(包括递归形式和迭代形式):
#include <stdio.h>
static int count = 0;
/*
**函数功能: 递归法求第n个斐波那契数
**参数说明: @n : 斐波那契数的序号
**返回值: 第n个斐波那契数
*/
long Recursion_fibonacci(int n)
{
if (n <= 2)
{
return 1;
}
//统计计算Fibonacci(3)的冗余次数
if (n == 3)
{
count++;
}
return Recursion_fibonacci(n - 1) + Recursion_fibonacci(n - 2);
}
/*
**函数功能: 迭代法求第n个斐波那契数
**参数说明: @n : 斐波那契数的序号
**返回值: 第n个斐波那契数
*/
long Loop_fibonacci(int n)
{
//保存三个相邻的斐波那契数
long first_fib;
long second_fib;
long third_fib;
first_fib = second_fib = 1; //前两个斐波那契数都是 1
third_fib = first_fib + second_fib;
while (n > 2)
{
first_fib = second_fib;
second_fib = third_fib;
third_fib = first_fib + second_fib;
n--;
}
return second_fib;
}
int main(void)
{
int n;
while (1)
{
scanf("%d", &n);
getchar();
printf("第 %d 个斐波那契数是 %d \n", n, Recursion_fibonacci(n));
printf("递归计算Fibonacci(3) %d 次\n", count);
printf("第 %d 个斐波那契数是 %d \n\n", n, Loop_fibonacci(n));
}
return 0;
}
运行截图:
四、怎么消除这种恐怖的开销呢?
当然是变递归为循环咯!上面的迭代法求斐波那契数效率可比递归法高了了几十万倍呢!所以能用迭代法替代的递归,就用迭代替代递归吧!