递归与迭代


递归和迭代的区别


递归就是不断调用自身,就是A调用A的过程。递归会不断使用栈来存过程,占用的空间很大。很容易造成堆栈溢出的情况,改进可以使用尾递归的形式。递归有两个过程:

1)递推;

2)回归。

对于1+2+3+…+n这种问题,递归方式求解:

1
2
3
4
5
6
7
int  sum1( int  n)
{
     if (n == 0)
         return  0;
     else
         return  n+sum1(n-1);
}
占用的空间形式是:

sum(5)
5+sum(4)
5+4+sum(3)
5+4+3+sum(2)
5+4+3+2+sum(1)
5+4+3+2+1+sum(0)
5+4+3+2+1+0
5+4+3+2+1
5+4+3+3
5+4+6
5+10
15



迭代是A不断的调用B的过程,使用一个循环语句的形式。

使用迭代的方式:

1
2
3
4
5
6
7
int  sum2( int  n)
{
     int  ret =  0 ;
     for ( int  i =  1 ;  i <= n; i++)
               ret += i;
     return  ret;
}

计算的过程是:

0+1=1
1+2=3
3+3=6
6+4=10
10+5=15

尾递归:

一个递归函数,它的计算过程是迭代的,就是尾递归函数,记住递归调用在递归实例中恰好以最后一步操作的形式出现。

Here's a tail-recursive version of the same function:

int tailrecsum(x, running_total=0):
    if x == 0:
        return running_total
    else:
        return tailrecsum(x - 1, running_total + x)

Here's the sequence of events that would occur if you called tailrecsum(5), (which would effectively be tailrecsum(5, 0), because of the default second argument).

tailrecsum(5, 0)
tailrecsum(4, 5)
tailrecsum(3, 9)
tailrecsum(2, 12)
tailrecsum(1, 14)
tailrecsum(0, 15)
15


这是尾递归:
function f(x) {
   if (x === 1) return 1;
   return f(x-1);
}

(这个程序没什么意义,仅作为理解辅助之用)。

这不是尾递归:

function f(x) {
   if (x === 1) return 1;
   return 1 + f(x-1);
}

后者不是尾递归,是因为该函数的最后一步操作是用1加上f(x-1)的返回结果,因此,最后一步操作不是调用自身。注意,后面这段代码的递归也发生在函数末尾,但它不是尾递归。 尾递归的判断标准是函数运行最后一步是否调用自身,而不是是否在函数的最后一行调用自身。因此阶乘n!的递归求法,尽管看起来递归发生在函数末尾,其实也不是尾递归:

function factorial(n) {
   if (n === 1) return 1;
   return n * factorial(n-1); // 最后一步不是调用自身,因此不是尾递归
}

使用尾递归可以带来一个好处:因为进入最后一步后不再需要参考外层函数(caller)的信息,因此没必要保存外层函数的stack,递归需要用的stack只有目前这层函数的,因此避免了栈溢出风险。

一些语言提供了尾递归优化,当识别出使用了尾递归时,会相应地只保留当前层函数的stack,节省内存。

所以,在没有尾递归优化的语言,如java, python中,鼓励用迭代iteration来改写尾递归;在有尾递归优化的语言如Erlang中,鼓励用尾递归来改写其他形式的递归。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值