C语言学习日记5:函数递归

递归的概念

在C语言中,函数自己调用自己就是函数递归

递归的思想是把复杂的问题简单化,不断拆分成子问题来解决,直到子问题不能再进行拆分,递归结束。就是一层一层剥洋葱,大事化小事的过程

递是递推,归是回归

递归是需要前提条件的:

递归存在限制条件时,当满足了这个限制条件,递归就停止了

每次递归调用函数之后,会越来越接近这个限制条件

递归的举例

阶乘的计算

4!        =       4*3*2*1

3!        =        3*2*1

2!        =        2*1

1!        =        1

规定0!        =        1

这就是阶乘的基本规律

我们仔细观察可以总结出一个公式

n! =   n*(n - 1)!

我们可以照着这个公式写一个阶乘的函数Fact

int fact(int n)

{

        if(n == 0)

                return 0;

        else

                return  n * Fact(n - 1);

}

我们这时候就用到了递归,将n!化为n*(n - 1)!

而此时(n - 1)!我们又未知,继续拆分化小,直到 0!为止

此时代码就很很好写了

# include <stdio.h>
int Fact(int n)//创建实现阶乘的函数
{
	if (n == 0)
		return 1;
	else
		return n * Fact(n - 1);
}

int main()
{
	printf("请输入一个整数来计算他的阶乘\n");
	int i = 0;
	scanf("%d", &i);
	Fact(i);//调用函数
	int fact = Fact(i);
	printf("%d\n", fact);
	return 0;
}

我们用一幅图来解

顺序打印一个整数的每一位

再举个例子,前面我们倒序打印过,这次顺序用递归如何实现?

先看个例子:123

怎么得到3?———— > 123%10 == 3

怎么得到12?————>123 / 10 == 12

按照这个顺序下去,我们就能得到3 2 1 

就按照这个思路,设计一个函数Print来打印n的每一位,将函数拆分再拆分

void Print(int n)//此函数不需要返回类型

{

        if(n > 9)

        {

                Print(n / 10);

        }

        printf("%d ", n % 10); 

}

还是以123举例,打印123就可以分为两步

第一步:Print(123 / 10)//打印12

第二步:printf(123 % 10)//打印3

           Print(123)

====> Print(123)                                        +printf(3)

====> Print(12)                                 +printf(2)

====> print(1)                                     

#include <stdio.h>
void Print(int n)
{
	if (n > 9)
	{
		Print(n / 10);
	}
	printf("%d ", n % 10);
}

int main()
{
	int i = 0;
	printf("请输入一个整数\n");
	scanf("%d", &i);
	Print(i);
	return 0;
}

运行结果

把Print(1234) 打印1234每⼀位,拆解为先Print(123)打印123的每⼀位,再打印得到的4
把Print(123) 打印123每⼀位,拆解为先Print(12)打印12的每⼀位,再打印得到的3
直到Print打印的是⼀位数,直接打印就好

递归和迭代

有些时候,我们使用递归会使重复运算次数大大增加,效率降低

比如打印第n个斐波那契数

我们定义一个Fib函数

则由公式很容易写出递归代码

int Fib(int n)
{
    if(n <= 2)
        return 1;
    else
        return Fib(n - 2) + Fib(n - 1);
}

#include <stdio.h>
int Fib(int n)
{
    if (n <= 2)
        return 1;
    else
        return Fib(n - 2) + Fib(n - 1);
}
int main()
{
    int i = 0;
    scanf("%d", &i);
    int fact = Fib(i);
    printf("%d\n", fact);
    return 0;
}

我们可以看到如果数据过大,运算效率大大降低,CPU占用很大

我们来看一看第三个斐波那契数一共被算了几次

int count = 0;
int Fib(int n)
{
    if (n == 3)
        count++;
    if (n <= 2)
        return 1;
    else
        return Fib(n - 2) + Fib(n - 1);
}
int main()
{
    int i = 0;
    scanf("%d", &i);
    int fact = Fib(i);
    printf("%d\n", fact);
    printf("count = %d\n", count);
    return 0;
}

这个重复计算次数非常多,我们就按照斐波那契数的定义去写代码呢?

#include <stdio.h>
int Fib(int n)
{
	int a = 1;
	int b = 1;
	int c = 1;
	while (n > 2)
	{
		c = a + b;
		a = b;
		b = c;
		n--;
	}
	return c;
}
int main()
{
	int i = 0;
	scanf("%d", &i);
	int fact =Fib(i);
	printf("%d\n", fact);
}

所以对于递归和迭代,我们在写代码时需要注意:

如果代码合理,能用递归就可以用递归,用少量代码即可实现大量运算

如果代码存在缺陷,此时就需要迭代了

  • 18
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值