递归

递归是一种编程技巧,表现为程序调用自身。它通过解决规模更小的子问题来求解原问题,常用于简化复杂问题。斐波那契数列是递归的经典示例。虽然递归使代码简洁易懂,但可能导致效率降低和栈溢出,因此使用时需谨慎。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基本思想:

        生活中有这样的例子:假如一个人站在两面相对的镜子之间,那么可以在其中一面镜子中看到自己,同时镜子中的自己后面又有一面镜子,镜子里面又是自己,这样重叠反复下去;再如,有些家庭喜欢每年照一副团圆照,每年照相时都拿着上一年的照片,这样第二年的照片中就会出现照片中的人拿着的照片里面有人拿着照片这样的现象,多年之后,这样现象更加重重叠叠……以上两种情况其实都是递归的表现。

        从程序设计的角度看,递归实际上是让程序调用自身的一种编程技巧。还是以上面两个情况为例,如果把“镜子反射对面镜子的内容”和“每年拿着上一年的照片照相”看作函数,那么它们确实是在不断地调用自身。不过这两个例子只是递归在实际生活中的表现而已,和程序设计中的递归还不太一样。程序设计中的递归表示一个过程或函数在其定义或说明中直接或间接调用自身的一种方法,它通常把一个大型复杂的问题转化为一个与原问题相似的规模较小的问题来求解。由于与原问题相似,规模小的问题依旧可以使用原来的算法进行求解,并且能够更容易地被求解,这些子问题的解就可以共同构成原问题的解。

        递归策略只需少量的代码就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。一般来说,构成递归需要具备以下两个条件:首先,子问题和原始问题要执行的操作应该是一致的,并且通常来说,子问题规模更小,更为简单;其次,不能无限制地调用自身,需要有一个出口,化简为非递归的情况进行处理。

        斐波那契数列是一个比较典型的递归的例子,它指的是这样一个数列:0,1,1,2,3,5,8,13,21,……。在数学上,斐波那契数列如下方方式定义:F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2),  (n>=2,n属于正整数)。根据其定义方式可以看出,当n>=2时,数列的每一项都等于前两项之和。也就是说,如果要求出数列的第n项,只需要先求出第(n-1)项和第(n-2)项,然后再把它们相加就可以了;而要求出数列的第(n-1)项和第(n-2)项,则需要分别求出第(n-2)项和第(n-3)项、第(n-3)项和第(n-4)项;这样一次递归下去,求解问题的规模是在不断减小的。直到第1项和第0项可以直接由定义得到,然后所需要求解的项就可以依次解得了。如果不用递归式的定义,斐波那契数列也有通式。很明显,通过递归定义的通项公式要简单得多。实际上,递归往往可以使得算法的描述更加简洁且易于理解。

        但是,思路简洁所带来的代价是运行效率的降低。递归算法解题相对常用的算法如普通循环等,运行效率是比较低的。在递归调用的过程中,系统为每一层的返回点、局部变量等开辟了栈来存储。递归次数过多,容易造成栈的溢出。因此,应该尽量避免使用递归,除非没有更好的算法,或者在某种特定情况下递归更为适合。

       递归方法的总体思想是将待求解问题的解看作输入变量x的函数f(x),通过寻找函数g,使得f(x)=g(f(x-1)),并且已知f(0)的值,就可以通过f(0)和g求出f(x)的值。这种思想也可以推广到多个输入变量x、y、z等,x-1也可以推广到x-2等,只要递归朝着出口的方向前进就可以了。

下面这个例子说明了斐波那契的递归和递推的执行时间比较:斐波那契递归与递推执行效率比较

很明显递推要快的多,递归执行的效率真的低。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值