一文读懂递归函数

声明:本文档参考c和指针,如有侵权请联系本人删除!

1、什么是递归函数?

递归函数是直接或间接调用自身的函数。

2、什么情况下可以使用递归函数。

(1)存在限制条件,且当到达限制条件时递归便不再继续。
(2)每次递归之后越来越接近限制条件。

3、递归函数举例

3.1 将二进制整数转换为字符

题目:给出一个整数值7788,我们需要转换成'7'、'7'、'8'、'8'字符输出到屏幕。
如果可以使用printf格式化输出,我们可以直接%d输出7788到屏幕上,但是printf又是怎么实现的。
  • 采用的编程思想是把这个值反复除以10,并打印各个余数。
#include <stdio.h>

void binary_to_ascii(unsigned int value)
{
    unsigned int quotient;
	 
    quotient = value/10;
    if(quotient != 0) 
        binary_to_ascii(quotient);
    putchar(value%10 + '0');
}

 在上述程序中,递归的限制条件是quotient为0,在每次调用递归之前,我们都把quotient除以10,所以每调用一次递归,它的值就越来越接近0。
递归是如何正确地顺序打印这些字符的呢?
 (1)每次递归前将参数值除以10
 (2)如果quoient不等于0,则调用递归打印quoient各位数字。
 (3)打印步骤(1)的余数
注意:递归函数的每次调用都会把上一个函数的变量压入堆栈中,重新产生一批新的变量。

3.2 计算n的阶乘

阶乘的数学描述:n=1*2*3*…n
在这里插入图片描述(1)当计算到n为0时,递归不再继续,满足限制条件
(2)每调用一次递归,n的值越接近0,满足调用递归后不断逼近限制条件。
实现如下:

#include <stdio.h>

unsigned int factorial(unsigned int n)
{
    if(n==0)
	return 1;	
    return n*factorial(n-1);	
} 

3.3 斐波那契数列

斐波那契数列指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……
数学描述:F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*
在这里插入图片描述
(1)当计算到n为2时,递归不再继续,满足限制条件
(2)每调用一次递归,n的值越接近2,满足调用递归后不断逼近限制条件。
实现如下:

#include <stdio.h>

unsigned int fibonacci(unsigned int n)
{
    if(n<=2)
    	return 1;
    return fibonacci(n-1)+fibonacci(n-2);
}

4、使用递归的缺点,引出迭代

 我们知道,调用递归函数时,系统需要将当前的现场压入堆栈中保存起来,调用完成后再恢复现场,所以当调用递归次数很多时将涉及到堆栈的不断开销,降低系统性能。
 (1)阶乘使用递归实现时,计算n的阶乘就要调用n-1次自身函数;
 (2)斐波那契数列调用次数更是恐怖,每个递归调用都触发另外两个递归调用,而这两个调用的任何一个还将触发两个递归调用,再接下去也是如此。举个例子,在递归计算Fibonacci(10)时,Fibonacci(3)的值被计算了21次,但是,在递归计算Fibonacci(30)时,Fibonacci(3)的值被计算了317811次,可以看出开销是相当恐怖的。
 基于此,我们可以寻找一种可以实现同样功能,但开销却小得多的方法,也就是迭代法

4.1什么是迭代法

迭代法也称辗转法,是一种不断利用变量旧值递推新值的过程

4.2 迭代法计算n的阶乘

迭代法计算n的阶乘的步骤
 (1)定义result =1 ;
 (2)当n>1时,result =result *n,n自减1;
 (3)返回result值
程序如下:

#include <stdio.h>

long factorial(int n)
{
    long result=1;
    
    while(n>1)
    {
        result *= n;
        n--;	
    }
    return result;
}

 上面程序,不断利用result旧值重新计算生成新值result,直到循环条件不成立。与递归法对比,不管n值多大,堆栈的开销不变,且实现起来也比较简单,而递归法时,n值很大时,堆栈的开销将不得不重视。

4.3 迭代法计算斐波那契数列

伪代码步骤:
 (1)定义当前结果result为0,上一次结果previous_result=1,上上次结果为next_older_result;
 (2)循环判断n是否大于2,满足则n自减1,并将上一次结果previous_result赋给上上次结果next_older_result,当前结果result赋给上一次结果previous_result,接着计算当前结果result等于上一次结果和上上次结果之和。
 (3)返回计算结果result
程序如下:

#include <stdio.h>
long fibonacci(int n)
{
    long result;
    long previous_result;//前一个值
    long next_older_result;//前前值
	
	result=previous_result=1;
	
    while(n>2)
    {
        n--;
        next_older_result=previous_result;
        previous_result=result;
        result=next_older_result+previous_result;

    }
    return result;
}

在这里插入图片描述
 上述迭代法是利用旧值previous_result和result不断更新新值。编程思想是每循环一次,将previous_result的值赋给next_older_result,result的值赋给previous_result,然后计算next_older_result和previous_result之和。

5、使用递归时注意事项

(1)判断是否满足使用递归条件
(2)如果堆栈开销巨大,是否有其他简单方法可替代
(3)如果使用递归能大大简化程序的复杂性,可着重考虑递归

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五彩缤纷的代码世界

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值