递归与尾递归
递归函数具有结构清晰,调用容易的优点。但是递归的过程中,递归函数将会被反复的调用,因此会在栈中占用非常大的空间来保存函数的上下文信息,若是递归调用的层次非常深的话,对栈的存储资源利用是十分低效的。为了克服上述的缺点,现代编译器,提出了尾递归的概念
那么什么是尾递归呢?尾递归是指当编译器检测到一个函数调用是尾递归的时候,它就覆盖当前的活跃记录而不是在栈中创建一个新的。因此只要我们能把递归调用都化成尾递归的形式,对栈空间的使用量将会大大减少,程序的实际运行效率也会大大提高。
形式上说,当递归调用是整个函数体最后执行的语句并且它的返回值不属于表达式的一部分时,这个递归调用就是尾递归。
下面给出两个计算阶乘的例子来区别尾递归和普通递归
int factorial_1(n){ if(n<1){ return 1; } else{ return n*factorial_1(n-1); } }
第一种方式是传统的递归方式,当n>1的时候,每一次的return语句都不完全依赖于下一层递归调用的结果,因此编译器不得不把当前调用的信息保存在栈中
int factorial_2(int n,int p) { if(n<1){ return p; } else{ return factorial_2(n-1,n*p); } }
第二种方式当n>1的时候return的语句完全依赖于下一次的递归调用,而且函数调用的情况只是参数发生了变化,因此编译器不用在栈中重新分配空间对函数信息进行保存,只用把现有的函数参数改成新的参数即可
在算法设计的过程中,递归是我们经常需要遇到的问题,为了提高递归调用的效率,请尽量使用尾递归的形式。
---恢复内容结束---
---恢复内容结束---