scala递归与尾递归

众所周知,函数的递归是任何一门语言的噩梦,java的递归会进行压栈的操作,如果递归次数过多,代码不够完善,会造成栈溢出,scala也是如此。

首先什么是压栈呢?

简单来说,当用到某些参数或者调用函数的时候,会将这些数据压入栈中,在计算机系统中,栈数据为先进后出的,也就是说最先使用的数据会被之后关联的数据压在底下,如果要释放该数据,需要先释放在它之上的数据,也就是后进栈的数据。递归函数会不停的调用自身,进行压栈,直到递归结束才会停止压栈的行为,占据栈内存会随着递归次数的增加而指数型增长,最终导致栈溢出。

那么递归函数是什么?

def loopRecursion(n:Int)={
    var res=1
    for (i<- 1 to n) res*=i
    res
}

如上图所示,是一个用for循环实现10的阶乘的函数,我们同样能够递归函数实现该功能。

def recursion(n:Int):Int={
    if(n==1) 1
    else recursion(n-1) * n
}

如上图,这种在函数体中进行自身调用行为的函数,我们称之为递归函数,递归并非不能使用,只是这种语法不是正确的使用方式:如果要得到n的阶乘的结果,需要根据n-1的阶乘的结果再乘上一个n,循环往复,直到得到1的阶乘为止,然后再挨个得出各级的结果。由于要用到除自身函数外的参数n,在得出结果、返回函数返回值之前,该函数的参数是一直压在栈中不能出栈的,这样栈中只会不停的增加数据,而不会释放数据,直到到达阙值,容易造成栈溢出。

尾递归函数又是什么呢?它为什么能解决递归的栈溢出问题?

def recursion1(n:Int):Int={

    //真正循环的是func函数
    def func(n1:Int,res:Int):Int={
        if (n==1) res else func(n-1,res*n)
    }
    func(n,1)

}

尾递归虽然也是递归,但是它并不会由递归而造成栈溢出,因为尾递归函数不需要使用除开本函数外的参数,因此尾递归函数在将值存入下次的调用的初始值后就弹出栈了,栈内存也就不会溢出。

如何实现尾递归函数?

很简单的方式,我们参考for循环,可以对返回值进行存储,在该函数中嵌套一个真真的循环函数,将原函数返回值设为内部循环函数输入参数中的一员,该方法适用绝大部分情况。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值