我的理解就是循环调用本函数,其中
1.存在限制条件,当满足这个限制条件时,递归便不再继续。
2.每次递归调用之后越来越接近这个限制条件
先举个例子来了解一下
#include<stdio.h>
void test_fac(int a)
{
printf("第%d次调用,n的地址时%p\n", a, &a);
if (a < 4)
{
test_fac(a + 1);
}
printf("第%d次调用,n的地址时%p\n", a, &a);
}
int main()
{
test_fac(1);
return 0;
}
解释:main函数中调用test_fac(1)函数,并传递值1,进入循环体后,系统会为形参a开辟内存,同时有一个首地址,这里明显可以看出是000000DA0D98FAE0,由于a<4,进入函数test_fac(2),暂时不会执行下面的打印语句。第二次进入函数后,系统再次为形参开辟空间,首地址是000000DA0D98F9E0,重复上述操作,知道当a=4时,不满足a<4,打印最后一条语句,结束最后第四次调用,并将控制权返回给上一级,打印最后一条语句,执行完后,又将控制权交给上一级,知道回到第一级结束。
这就是大致过程,下面我们还可以看一个经典的用递归函数解决得到问题,它就是斐波拉契数列,即从第三项起,下一项等于前两项之和。
代码实现:
#include<stdio.h>
long fib(int n)
{
long num;
if(n<=2)
{
return 1;
}
else
{
num = fib(n - 1) + fib(n - 2);
}
return num;
}
int main()
{
int n;
long num;
scanf("%d", &n);
printf("计算到第%d项\n", n);
num=fib(n);
printf("num=%ld\n", num);
return 0;
}
当然这个代码还可以优化,因为在计算的时候,会有重复计算的结果。递归最大的特点就是在解决这种由多个子问题构成的时候,会非常的方便,同时对于较少的数据运行时,递归比较实用,总的来说就是利用空间换时间。意思就是计算第五个斐波那契数需要先计算第3和第4个斐波那契数,但是计算第4个的时候又要计算第3个。但是由于处于不同的递归深度,递归函数不知道自己算过了,那么就出现了重复运算。而且恐怖的是:这种重复计算应该是一个指数增长的。
代码优化:
long long func_1(int n) {
if (n == 1 || n == 2) {
record[n] = 1;
return record[n];
}
if (record[n])//如果在函数递归中已经计算过这个值直接返回
return record[n];
else {
record[n] = func_1(n - 1) + func_1(n - 2);
return record[n];
}
}
今天终于弄懂了用记录来减省时间,下面是写的代码,主要是为了记录。
/* 程序的功能是:从键盘输入一个整数n(n≥0)和x,计算对应的n阶勒让德多项式Pn(x)的值,并按示例格式输出相应信息。
n阶勒让德多项式Pn(x)的定义如下:3270243680341106588372697088.000000.23200364498382.105469.
┌ 1 (n=0)
Pn(x)= ├ x (n=1)
└((2n-1)xPn-1(x) - (n-1)Pn-2(x)) / n (n>1)*/
#include <stdio.h>
#include<stdlib.h>
double fun_calculate(int n, int x,double* rerord);
int main(void)
{
double Pnx;
int n, x;
printf("please input n, x: ");
scanf("%d,%d", &n, &x);
double* record = (double*)malloc(sizeof(double) * (n + 1));
if (!record)
return 0;
for (int i = 0; i < n + 1; i++)
{
record[i] = 0;
}
Pnx = fun_calculate(n, x,record);
printf("Output:\nThe answer is %.6f.\n", Pnx);
free(record);
return 0;
}
double fun_calculate(int n, int x,double* record)
{
double Pn_1x, Pn_2x;
if (n == 1)
{
record[n] = x;
return record[n];
}
else if (n == 0)
{
record[n] = 1;
return record[n];
}
if (record[n])
{
return record[n];
}
else if(n>=2)
{
Pn_1x = fun_calculate(n - 1, x,record);
Pn_2x = fun_calculate(n - 2, x,record);
}
record[n] = ((2 * n - 1) * x * Pn_1x - (n - 1) * Pn_2x) / n;
return record[n];
}
在main函数里动态申请一块空间用来记录每次函数递归计算的结果,从调试的角度看节省了很多时间,可以自己画图看一下。