递归、尾递归与迭代
很久以前写过一篇《递归与迭代》,写得不是很好。可能是我自己也没把思路理清楚,现在就有了个重新整理思路炒冷饭的机会,也算是一个新的开始吧。 首先解释一个术语叫“尾调用”。直接从wiki的“ 尾调用 ”条目抄:尾调用是指一个函数里的最后一个动作是一个函数调用的情形:即这个调用的返回值直接被当前函数返回的情形。这种情形下称该调用位置为尾位置。若这个函数在尾位置调用本身(或是一个尾调用本身的其他函数等等),则称这种情况为尾递归,是递归的一种特殊情形。 比如,下面这个是尾调用: return f(); 而这个不是: return 1 + f(); 关于尾调用,有个重要的优化叫做尾调用消除。经过尾调用消除优化后的程序在执行尾调用时不会导致调用栈的增长。其实,这个优化可能不算是优化。因为在某些计算模型中,尾调用天然不会导致调用栈的增长。在EOPL提到过一个原理: 导致调用栈增长的,是对参数的计算,而不是函数调用。 由于尾调用不会导致调用栈的增长,所以尾调用事实上不像函数调用,而更接近GOTO。尾递归则等同于迭代,只是写法上的不同罢了。 下面以计算幂为例,分别用递归、尾递归和迭代三种方法实现程序。其中尾递归方法是递归方法的改进,而迭代方法纯粹是从尾递归方法翻译而来。 问题 已知数(整数,或浮点数,这里假设是整数)\(b\) 和非负整数\(n\) ,求\(b\)的\(n\)次幂\(b^n\)。