Scala进阶之路-尾递归优化
Scala进阶之路-尾递归优化
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
递归调用有时候能被转换成循环,这样能节约栈空间。在函数式编程中,这是很重要的,我们通常会使用递归方法来遍历集合。而不是所有的递归都能被优化。递归之所有能被优化是在指在函数的最后一行为递归调用(即尾递归),并且这个递归调用没有其它元素参与。
一.什么情况能导致栈的溢出
1>.循环调用
答:循环调用并不会导致栈的溢出,因为循环是一个压栈和弹栈的过程。
2>.递归调用
答:递归调用会导致栈的溢出。因为递归调用一直在压栈,而之前的栈并不会释放资源,这样随着压栈的堆积,栈空间溢出那是迟早的事儿。
3>.尾递归
答:可以进行优化,将递归转换成循环实现,避免栈的溢出。
二.尾递归优化案例展示
1>尾递归不能有其它参数参与
我们先以下案例:
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/
package cn.org.yinzhengjie.function object TailRecursion {
//定义递归函数
def sum(args:Seq[Int]):BigInt = {
if(args.isEmpty) {
0
} else{
args.head + sum(args.tail)
}
}
def main(args: Array[String]): Unit = {
sum(1 to 10000)
}
}
以上代码测试结果如下:
2>.尾递归优化
我们将上面的代码稍微进行改动,就可以轻松实现尾递归优化啦。具体代码如下:
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/
package cn.org.yinzhengjie.function object TailRecursion {
//定义尾递归函数
def sum(x:Seq[Int] , part :BigInt):BigInt = {
if(x.isEmpty) {
part
} else {
sum( x.tail ,x.head + part)
}
}
def main(args: Array[String]): Unit = {
val res = sum(1 to 1000000000,0)
println(s"res的结尾为:${res}")
}
}
测试结果如下:
三.如果编写尾递归函数
所谓的尾递归就是最后一步如果是递归操作本身(即没有和其它参数参与),此时它就是一个尾递归函数,它就变成循环了,因此不会出现栈溢出的情况。能实现尾递归的原理就是当然的栈并不需要从下一个栈中拿数据才能释放。也就是说,当前的栈调用下一个栈时不依赖下一个栈返回数据才能结束,因此当它调用下一个栈时,也就可以让当前的栈执行弹栈操作,当下一个栈执行完毕时,也不需要下下个栈返回数据,因此,下一个栈也可以实现弹栈操作,综上所述,尾递归的就和咱们写的死循环是一个原理啦,就是实现压栈和弹栈的过程,因此始终不会栈溢出的情况哟!
我们再举一个尾递归的例子如下:
/*
@author :yinzhengjie
Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
EMAIL:y1053419035@qq.com
*/
package cn.org.yinzhengjie.function object TailRecursion {
//定义尾递归函数
def sayHello(str:String):Unit= {
println(str)
sayHello(str)
}
def main(args: Array[String]): Unit = {
sayHello("yinzhengjie")
}
}
以上程序我执行了5分钟,依旧没有出现栈溢出的情况,
当然如果是你讲上面的尾递归函数的两行代码调换一下,当然依旧还是递归函数,但最后一行不是递归函数本身了,因此不是尾递归函数,很显然会出现栈内存溢出。
Scala进阶之路-尾递归优化的更多相关文章
- Scala进阶之路-Spark本地模式搭建
Scala进阶之路-Spark本地模式搭建 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Spark简介 1>.Spark的产生背景 传统式的Hadoop缺点主要有以下两 ...
- Scala进阶之路-Scala中的泛型介绍
Scala进阶之路-Scala中的泛型介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 通俗的讲,比如需要定义一个函数,函数的参数可以接受任意类型.我们不可能一一列举所有的参数类 ...
- Scala进阶之路-面向对象编程之类的成员详解
Scala进阶之路-面向对象编程之类的成员详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Scala中的object对象及apply方法 1>.scala 单例对象 ...
- Scala进阶之路-Scala中的枚举用法案例展示
Scala进阶之路-Scala中的枚举用法案例展示 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. Scala中的枚举值和Java中的枚举值有点差别,不过使用起来也都差大同小异,我这 ...
- Scala进阶之路-Scala中的高级类型
Scala进阶之路-Scala中的高级类型 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.类型(Type)与类(Class)的区别 在Java里,一直到jdk1.5之前,我们说 ...
- Scala进阶之路-Scala中的Ordered--Ordering
Scala进阶之路-Scala中的Ordered--Ordering 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 说道对象的比较,在Java中大家最熟悉不过的就是实现类本身实 ...
- Scala进阶之路-反射(reflect)技术详解
Scala进阶之路-反射(reflect)技术详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. Scala中的反射技术和Java反射用法类似,我这里就不一一介绍反射是啥了,如果对 ...
- Scala进阶之路-正则表达式案例
Scala进阶之路-正则表达式案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 废话不多说,正则大家都很清楚,那在Scala如何使用正则了?我们直接上个案例,如下: /* @au ...
- Scala进阶之路-进程控制之执行shell脚本
Scala进阶之路-进程控制之执行shell脚本 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 废话不多说,我这里直接放一个案例. /* @author :yinzhengjie ...
随机推荐
- github学习步骤
组员1: 王文政 201303011159 作业网址 :https://github.com/1246251747/3/blob/master/jjj.txt 心得: 1. 申请gi ...
- css - 背景图片充满整个屏幕
body { /* 加载背景图 */ background: url("../static/images/index/backImg.jpg") no-repeat; /* 背景图 ...
- Java面向对象(Eclipse高级、类与接口作为参数返回值)
面向对象 今日内容介绍 u Eclipse常用快捷键操作 u Eclipse文档注释导出帮助文档 u Eclipse项目的jar包导出与使用jar包 u 不同修饰符混合使用细节 u 辨析何时定义变 ...
- jmeter 使用csv文件 注意项
1.首先在jmeter 中导入csv文件时我们程序并不知道csv文件中有多少行 : >1.获取的时候 使用 循环控制器来获取csv文件中的所有数据 : 通过 ${__jexl3("${ ...
- ubuntu默认壁纸位置
usr/share/backgrounds和usr/share/wallpapers
- AntDesign从入门到精通
第一 设计原则 官方网址:https://ant.design/index-cn 需要做出更好的设计决策,给予研发团队一种高确定性.低熵值的研发状态.同时,不同设计者在充分理解业务述求后,基于 Ant ...
- XE2 运行时 item not found的解决办法
.net类库的原因. 将C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG下面的 machine.config.default 改名为machin ...
- JS中var声明与function声明两种函数声明方式的区别
JS中常见的两种函数声明(statement)方式有这两种: // 函数表达式(function expression) var h = function() { // h } // 函数声明(fun ...
- debian 系统安装配置apache
安装sshapt-get install ssh-server (安装失败请插入镜像)service ssh start Apache 服务安装apt-get install apache2 apa ...
- LOJ #6202. 叶氏筛法(min_25 筛)
题意 求 \([L, R]\) 之间的素数之和 . \(L≤10^{10},2×10^{10} \le R \le 10^{11}\) 题解 一个有点裸的 min_25筛 ? 现在我只会筛素数的前缀和 ...