线性递归和尾递归

线性递归:  即一般型的递归
    一个函数直接或间接地调用自身,是为直接或间接递归,在调用过程中,需要压栈,可能会导致程序崩溃。
尾递归:
   尾递归就是从最后开始计算, 每递归一次就算出相应的结果, 也就是说, 函数调用出现在调用者函数的尾部, 因为是尾部, 所以根本没有必要去保存任何局部变量. 直接让被调用的函数返回时越过调用者, 返回到调用者的调用者去.
例: 以阶乘来看两者的区别:
   阶乘: 5!=1*2*3*4*5    结果为:120

线性递归:
long Rescuvie(long n)

 {      
  return(n == 1) ? 1 : n * Rescuvie(n - 1);      
}      

调用过程如:
当n = 5时
对于线性递归, 他的递归过程如下:
Rescuvie(5)  

开始调用
{5 * Rescuvie(4)}
{5 * {4 * Rescuvie(3)}}
{5 * {4 * {3 * Rescuvie(2)}}}
{5 * {4 * {3 * {2 * Rescuvie(1)}}}}
{5 * {4 * {3 * {2 * 1}}}}
{5 * {4 * {3 * 2}}}
{5 * {4 * 6}}
{5 * 24}
120

尾递归:
long TailRescuvie(long n, long a) {      
  return(n == 1) ? a : TailRescuvie(n - 1, a * n);        
}      
long TailRescuvie(long n) {//封装用的      
  return(n == 0) ? 1 : TailRescuvie(n, 1);    

对于尾递归, 他的递归过程如下:
TailRescuvie(5)
TailRescuvie(5, 1)
TailRescuvie(4, 5)
TailRescuvie(3, 20)
TailRescuvie(2, 60)
TailRescuvie(1, 120)
120
 
尾递归易于在编译器层面优化。如果编译器未作优化,效果和线性递归差不多。
 
猴子吃桃问题:

猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾就多吃了一个。第二天早上又将剩下的桃子吃了一半,还是不过瘾又多吃了一个。以后每天都吃前一天剩下的一半再加一个。到第10天刚好剩一个。问猴子第一天摘了多少个桃子?

 

代码示例:

int sumPeach(int day)
{
	if (day == 10)
	{
		return 1;
	}
	return 2 * sumPeach(day + 1) + 2;
}

int tailSumPeach(int day, int total)
{
	if (day == 10)
	{
		return total;
	}
	return tailSumPeach(day + 1, 2 * total + 2);
}

 

posted @ 2012-09-07 10:27  lichongbin  阅读(1175)  评论(0编辑  收藏  举报