头递归和尾递归

《像程序员一样思考》一书对头递归和尾递归描述的非常精彩,他举了两个例子,“火车站台数鹦鹉”和“上下级委托事宜”。

火车站台数鹦鹉是这样的:有几个连续的火车站台,每个值班人员可以与其直接相邻的站台电话联系,第一个站台如何知道所有站台出现的鹦鹉的总数?

给出了两种思路:

第一种:

步骤 1.站台 1 把看到的鹦鹉报告给站台2,并询问,“总鹦鹉数量是多少”。得到回答后,加上本身看到的数量作为最终结果。

步骤 2.站台 2 把看到的鹦鹉数量加上站台 1 传入的数量传给站台3,并询问,“总鹦鹉数量是多少?”。得到回答后,把这个答案传给站台 1.

步骤 3.站台 3 把看到的鹦鹉数量加上站台 2 传入的数量传给站台4,并询问,“总鹦鹉数量是多少?”。得到回答后,把这个答案传给站台 2.

......

步骤 n.站台 n 看到了 x 只鹦鹉,并把 n - 1 站台报告的数量相加,传给 n - 1 站台。

这种思路是我们常用的,它就是尾递归。


第二种:

步骤 1.站台 1 询问站台 2 ,你得到的鹦鹉总数是多少?得到回答后,加上本身看到的数量作为最终结果。

步骤 2.站台 2 询问站台 3 ,你得到的鹦鹉总数是多少?得到回答后,加上本身看到的数量作为站台 2 的鹦鹉总数。

步骤 3.站台 3 询问站台 4 ,你得到的鹦鹉总数是多少?得到回答后,加上本身看到的数量作为站台 3 的鹦鹉总数。

......

步骤 n.返回站台 n 看到的鹦鹉数量。

这种思路是头递归。


具体来看看尾递归和头递归有什么区别

1.尾递归上的每一个节点都知道最终结果,有时候不利于信息隐藏(与特定的业务相关)。而头递归只有第一个节点知道最终结果。

2.尾递归需要向后一个调用传递信息(上面的例子中,前一个必须报告后一个他的数据),增加流量。而头递归不需要,它只需要传递尽可能少的数据。

3.尾递归的思路是先对问题有了一个复杂的思考,先做了很多事,这样可能会导致过度复杂,编写出错误的代码。而头递归的思路是不去关心问题的复杂性,他假设下一节点已经

计算好了,我如何去计算自身。


另一个例子限于文章篇幅,不予列出。

文中最后引出了“大递归思路”。调用链中每个节点都是对一个更小子集执行相同的步骤,但是,如何去操作这个更小子集,本身不是一个递归的问题。每位站台值班人员向下一站台发送请求,下一位值班人员采用了与上一位人员相同的计算方法,但他也可以不采用那个计算方法。每个调用节点只关心结果,不关心过程。“大递归思路”正是:如果在编写代码时采用某种约定,可以假装并没有发生递归。甚至可以用一种欺骗手段把迭代式实现转移到一个递归式实现,而不需要考虑递归是怎样解决问题的。

你可能感兴趣的:(算法)