递归

本文详细介绍了递归的概念,通过求解斐波那契数列展示了递归的实现过程,解释了递归函数如何通过不断调用自身获取前一步结果。同时,对比了递归与递推两种方法的优缺点,指出递归适合不追求高效但要求代码简洁明了的情况,而递推则在效率上有优势。
摘要由CSDN通过智能技术生成

递归

递归的定义

先来解释以下递归,其实很简单:就是函数在运行的过程中调用自己。在一个计算过程中,如果其中每一步都要用到前一步或前几步的结果,称为递归的。用递归过程定义的函数,称为递归函数。那么在数学中,关于递归函数的定义如下:对于某一函数f(x),其定义域是集合A,那么若对于A集合中的某一个值X0,其函数值f(x0)由f(f(x0))决定,那么就称f(x)为递归函数。像连加、连乘及阶乘都是递归函数,也都可以在计算中用递归实现。所以,我们可以在函数中以不断调用自己的方式来得到前一步的结果由此解决问题。

递归的实现

说了一些定义,或多或少还是有一点抽象。我们围绕下面这段求斐波那契数的代码来说明递归的本质。

int recursive_Fibonacci(int n)  //递归实现
{
    if(n == 1 || n== 2)
        return 1;
    else
        return recursive_Fibonacci(n-1)+recursive_Fibonacci(n-2);
}

斐波那契数列:已知f(1) = 1 , f(2) = 1 , 且满足关系式f(n) = f(n-1) + f(n-2),求 f(n)。
我们先用递归的思想试求出f(5):
f(5) = f(4) + f(3);
f(4) = f(3) + f(2);
f(3) = f(2) + f(1);
f(2) = 1; //已知
f(1) = 1; //已知

整体的求解思路就是这样的,想要得到f(5)的值,就要得到f(4)和f(3)的值,同样 f(4) 的值就要的到 f(3) 和 f(2)的值,f(3)的值要得到f(1) 和 f(2) 的值,那么重点来了,f(1)和f(2)的值 是已知的为 1。所以 f(3),f(4),f(5)的值就全都得出了。这个方法满足上述对于递归函数的定义:函数值f(x0)由f(f(x0))决定,也就是,这个过程的当前时刻的结果由上一刻的结果决定,所以我们只需要设计出一个求得上一步结果的函数,并且不断调用自身,就可以不断求得上一刻结果,直到我们执行到那个不需要上一刻结果就可以得出此刻结果的时候,结束调用。
讲到这里,相信大家已经开始了解了一些递归的思想,那么我们讲解以下求解f(4)的函数具体执行步骤:(以下 以 f 代替 recursive_Fibonacci)
1.首先进入 f(4) 函数体, 先执行 n == 1 || n== 2 ,否则执行return recursive_Fibonacci(n-1)+recursive_Fibonacci(n-2),这会进入 f(3)函数体。
2.进入 f(3)后,执行同样的流程,进入f(2)。
3. f(2) 判断成功,返回值为1,退回 函数 f(3) , 我们在进入 f(3)之前,执行到recursive_Fibonacci(n-1)+recursive_Fibonacci(n-2),此时recursive_Fibonacci(n-1)得到结果为 1,所以进入 f(n-2),也就是f(1)。
4. f(1)判断成功,返回 1, 退回 函数 f(3) ,我们之前执行得到了 f(2) 和 f(1) 的结果,所以 recursive_Fibonacci(n-1)+recursive_Fibonacci(n-2) 等于 2,f(3)函数返回,退回到f(4)。
5.在我们进入f(3)之前,我们执行到了recursive_Fibonacci(n-1)+recursive_Fibonacci(n-2),也就是 f(3) + f(2),那么 f(3) 已经都得到了结果为 2,所以 函数进入 f(2),同样的重复上述的流程,f(2)返回为1,退回到f(4)中,此时f(3) ,f(2) 的结果都已经得到,f(4) 函数返回,返回值为 3.

其实,递归的实现就像一个栈,一直在不停的入栈,出栈:
在当前函数求前一时刻结果时,需要把当前函数入栈,在函数执行结束后出栈,由此一来递归的实现就越发的明了了。而且,在函数中,不断的调用自身的过程也是要依照代码顺序执行的,跟着代码的顺序走永远是正确的。

由于这个过程需要不断的将函数压栈,出栈,所以递归的效率不是很高。但是优点在于,代码量少,并且思路简单明了,一般在不追求太高效率,并且递归可以实现的问题,递归属实是不错的选择。

递归与递推

说到递归,就不得不说一说递推了。对于递推大家应该很熟悉,最常见的就是由前一项得到后一项的结果。那么这个斐波那契数列也是可以用递推实现的:

int recurrence_Fibonacci(int n)  //递推实现
{
    int f1 = 1;
    int f2 = 1;
    if(n == 1 || n == 2)
        return 1;
    int f = 0;
    for(int i=3;i<=n;i++)
    {
        f = f1 + f2;
        f1 = f2;
        f2 = f;
    }
    return f;
}

相较于递归,这个递推实现代码明显对了一些,但是效率也更高了。
那么大家在解决问题时是选用递归还是递推就要有自己的取舍了:
递归:代码量少,思路明了,效率低
递推: 代码相较多,效率高。

另外,想要透彻了解递归最从数据结构中的栈入手。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值