来源:coderkian
链接:www.cnblogs.com/coderkian/p/3758068.html
递归函数具有很好的可读性和可维护性,但是大部分情况下程序效率不如非递归函数,所以在程序设计中一般喜欢先用递归解决问题,在保证方法正确的前提下再转换为非递归函数以提高效率。
函数调用时,需要在栈中分配新的帧,将返回地址,调用参数和局部变量入栈。所以递归调用越深,占用的栈空间越多。如果层数过深,肯定会导致栈溢出,这也是消除递归的必要性之一。递归函数又可以分为尾递归和非尾递归函数,前者往往具有很好的优化效率,下面我们分别加以讨论。
尾递归函数
尾递归函数是指函数的最后一个动作是调用函数本身的递归函数,是递归的一种特殊情形。尾递归具有两个主要的特征:
调用自身函数(Self-called);
计算仅占用常量栈空间(Stack Space)。
为什么尾递归可以做到常量栈空间,我们用著名的fibonacci数列作为例子来说明。
fibonacci数列实现方法一般是这样的,
intFibonacciRecur(intn){
if(0==n)return0;
if(1==n)return1;
returnFibonacciRecur(n-1) FibonacciRecur(n-2);
}
不过需要注意的是这种实现方法并不是尾递归,因为尾递归的最后一个动作必须是调用自身,这里最后的动作是加法运算,所以我们要修改一下,
intFibonacciTailRecur(intn,intacc1,intacc2){
if(0==n)returnacc1;
returnFibonacciTailRecur(n-1,acc2,acc1 acc2);
}
好了,现在符合尾递归的定义了,用gcc分别加-O和-O2选项编译,下面是部分汇编代码,
-O2汇编代码
FibonacciTailRecur:
.LFB12:
testl %edi,%edi
movl%esi,%eax
movl%edx,%esi
je.L4
.p2align4,,7
.L7:
leal(%rax,%rsi),%edx
decl%edi
movl%esi,%eax
testl %edi,%edi
movl%edx,%esi
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|