学习总结自《像程序员一样思考》V.Anton Spraul 著,徐波 译
递归,也就是一个函数直接或间接调用自身。
一般来说,递归可以分为直接递归和间接递归。直接递归,是指函数自己调用自己的情况,而间接递归,是指调用其他函数时,在其他函数中又调用了自己的情况。
现在,主要将递归分为头递归和尾递归来学习。
1.概念
头递归:递归发生在函数的其他处理代码之前(或理解为,递归发生在函数的头部或顶部)
尾递归:与头递归正好相反,递归发生在函数其他处理代码的后面(或理解为,递归发生在函数的尾部)
2.例子
1)多少只鹦鹉
现在有5个连续的火车站台(A,B,C,D,E),5个站台里都有鹦鹉,每个站台只能与直接相邻的站台通话,而负责人在A站台,问负责人如何知道这5个站台的鹦鹉总数。
方法1:
1》A站台计数他的站台的鹦鹉数量,7只鹦鹉;
2》A站台和B站台联系,告诉B站台当前的鹦鹉总数(一个站台),7只鹦鹉;
3》B站台计数他的站台的鹦鹉数量,5只鹦鹉;
4》B站台和C站台联系,告诉C站台当前的鹦鹉总数(前两个站台),12只鹦鹉;
5》C站台计数他的站台的鹦鹉数量,3只鹦鹉;
6》C站台和D站台联系,告诉D站台当前的鹦鹉总数(前三个站台),15只鹦鹉;
7》D站台计数他的站台的鹦鹉总数,10只鹦鹉;
8》D站台和E站台联系,告诉E站台当前的鹦鹉总数(前四个站台),25只鹦鹉;
9》E站台计数他的站台的鹦鹉总数,2只鹦鹉,得出5个站台的总鹦鹉数量是27只;
10》E站台向D站台反馈:鹦鹉总数是27只;
11》D站台向C站台反馈:鹦鹉总数是27只;
12》C站台向B站台反馈:鹦鹉总数是27只;
11》B站台向A站台反馈:鹦鹉总数是27只。
方法1采用的步骤提取如下:
1》对本站台的鹦鹉数量计数
2》把上一个站台的总鹦鹉数量与本站台的鹦鹉数量相加
3》与下一个站台通话,汇报当前的鹦鹉总数
4》最后等待总结过的反馈,待下一个站台将鹦鹉总数汇报给本站台后,然后把这个结果向上一个站台汇报。
方法2:
1》A站台与B站台通话:到你的站台为止的鹦鹉总数是多少;
2》B站台与C站台通话:到你的站台为止的鹦鹉总数是多少;
3》C站台与D站台通话:到你的站台为止的鹦鹉总数是多少;
4》D站台与E站台通话:到你的站台为止的鹦鹉总数是多少;
5》E是最后一个站台,收到D的消息后,计数他的站台的鹦鹉数量,2只鹦鹉;
6》E与D通话:目前为止,鹦鹉总数2只;
6》D站台计数他的站台的鹦鹉数量,10只鹦鹉,得到鹦鹉总数12只鹦鹉;
7》D与C通话:目前为止,鹦鹉总数12只;
8》C站台计数他的站台的鹦鹉数量,3只鹦鹉,得到鹦鹉总数15只鹦鹉;
9》C与B通话:目前为止,鹦鹉总数15只;
10》B站台计数他的站台的鹦鹉数量,5只鹦鹉,得到鹦鹉总数20只鹦鹉;
11》B与A通话:目前为止,鹦鹉总数20只;
12》A站台计数他的站台的鹦鹉数量,7只鹦鹉,得到鹦鹉总数27只。
方法2采用的步骤提取如下:
1》与下一站通话;
2》对当前站点的鹦鹉计数;
3》把当前站台的鹦鹉数量加上下一站点反馈的鹦鹉总数;
4》把相加所得的结果汇报给上一个站台。
从这个例子可以看出,方法1是先对本站点的鹦鹉数量进行处理后,再去询问下一个站台的鹦鹉数量,是属于尾递归的情况,而方法2是先进入到下一个站台,让下一个站台处理鹦鹉数量,得到下一个站台的鹦鹉数量后,再对该站台的鹦鹉数量进行计数相加,属于头递归的情况。
3.结论
头递归与尾递归相比,将处理过程置后,从递归的目的出发,将大问题细化成小问题,细化到可以解决的程度后,将结果一层层反馈,而较大细度的问题可以直接将该结果作为已知数据进行计算使用,使递归过程更加方便清晰。尾递归过程是先对当前细度的问题进行处理,但是该结果只是一个暂时值,需要将问题一层层细化后,每层对当前的暂时值进行计算操作,得到最终的结果,可以看做是一个不断修正的过程,所以尾递归过程相对头递归来说,计算较慢,所占资源也会较多。所以,建议采用头递归。
一般来说,头递归更加体现了递归的思想,大递归思想,在使用递归解决问题时,我们的思维应该有别于其他的函数的实现过程,在实现其他函数时,我们会细化各个过程,用程序化的思维来思考各个步骤,这个思维用在递归函数时,将会以尾递归的方式呈现出来,因为,我们都想尽可能完成函数功能,就会不自觉的将可以实现的功能写在了前面。大递归的思想就是让我们多在意递归函数的意义,我们在用递归函数实现某一功能时,应该时时牢记该递归函数的功能,多关注该问题与子问题之间的关系,尽可能用头递归的方式实现递归函数。