C语言factorail函数递归

文章讲述了递归函数的工作原理,以`test_fac`和斐波那契数列为例,强调了递归的结构和空间换时间的概念。同时介绍了如何通过记录避免递归中的重复计算,以`fun_calculate`函数优化计算勒让德多项式的示例。
摘要由CSDN通过智能技术生成

我的理解就是循环调用本函数,其中

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函数里动态申请一块空间用来记录每次函数递归计算的结果,从调试的角度看节省了很多时间,可以自己画图看一下。

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值