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进阶之路-尾递归优化的更多相关文章

  1. Scala进阶之路-Spark本地模式搭建

    Scala进阶之路-Spark本地模式搭建 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Spark简介 1>.Spark的产生背景 传统式的Hadoop缺点主要有以下两 ...

  2. Scala进阶之路-Scala中的泛型介绍

    Scala进阶之路-Scala中的泛型介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 通俗的讲,比如需要定义一个函数,函数的参数可以接受任意类型.我们不可能一一列举所有的参数类 ...

  3. Scala进阶之路-面向对象编程之类的成员详解

    Scala进阶之路-面向对象编程之类的成员详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Scala中的object对象及apply方法 1>.scala 单例对象 ...

  4. Scala进阶之路-Scala中的枚举用法案例展示

    Scala进阶之路-Scala中的枚举用法案例展示 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. Scala中的枚举值和Java中的枚举值有点差别,不过使用起来也都差大同小异,我这 ...

  5. Scala进阶之路-Scala中的高级类型

    Scala进阶之路-Scala中的高级类型 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.类型(Type)与类(Class)的区别 在Java里,一直到jdk1.5之前,我们说 ...

  6. Scala进阶之路-Scala中的Ordered--Ordering

    Scala进阶之路-Scala中的Ordered--Ordering 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   说道对象的比较,在Java中大家最熟悉不过的就是实现类本身实 ...

  7. Scala进阶之路-反射(reflect)技术详解

    Scala进阶之路-反射(reflect)技术详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. Scala中的反射技术和Java反射用法类似,我这里就不一一介绍反射是啥了,如果对 ...

  8. Scala进阶之路-正则表达式案例

    Scala进阶之路-正则表达式案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 废话不多说,正则大家都很清楚,那在Scala如何使用正则了?我们直接上个案例,如下: /* @au ...

  9. Scala进阶之路-进程控制之执行shell脚本

    Scala进阶之路-进程控制之执行shell脚本 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 废话不多说,我这里直接放一个案例. /* @author :yinzhengjie ...

随机推荐

  1. 使用eclipse利用Junit4进行程序模块的测试

    一.题目简介 通过用户输入年份和月份,然后在控制台显示该年该月的日历. 二.源码的github链接. https://github.com/zhangxinn/test/blob/master/Pri ...

  2. js选择排序。

    <script> , , , , , , , ]; ; j<len; j++ ){ // 假设min为最小值 var minIndex = j; var min = arr[j]; ...

  3. ntpdate[31915]: the NTP socket is in use, exiting

    [root@master local]# ntpdate cn.pool.ntp.org 10 Oct 13:24:36 ntpdate[31915]: the NTP socket is in us ...

  4. Delphi中根据分类数据生成树形结构的最优方法

    一. 引言:    TreeView控件适合于表示具有多层次关系的数据.它以简洁的界面,表现形式清晰.形象,操作简单而深受用户喜爱.而且用它可以实现ListView.ListBox所无法实现的很多功能 ...

  5. 什么样的 GitHub 才适合放简历上?

    为什么 GitHub 可以加分? 很多招聘描述上面都会备注 GitHub 是加分项,那么为什么它是加分项呢? 停,如果看到这里你还不知道 GitHub 是什么,可以看一下 Phodal的手记:http ...

  6. 如何停止处于stopping状态的windows服务

    工作中有时需要启动和停止windows service,有时候会出现服务处于stopping或者starting的状态,但是,在services界面中,start service/stop servi ...

  7. 一本通1601【例 5】Banknotes

    1601:[例 5]Banknotes 时间限制: 1000 ms         内存限制: 524288 KB [题目描述] 原题来自:POI 2005 Byteotian Bit Bank (B ...

  8. Java生成数独函数

    突然想写一下生成算法.代码注释的比较多,应该比较好理解 使用了递归 import java.util.ArrayList; public class Sudoku { static int sudok ...

  9. Ajax中返回数据的格式

    Ajax中常见的返回数据的格式有三种:分别为文本,XML和JSON 返回的文本格式我们在上一堂课Ajax基础介绍中已经介绍过了 Ajax.php Form.html:通过Ajax对象的response ...

  10. 洛谷 P2341 [HAOI2006]受欢迎的牛 解题报告

    P2341 [HAOI2006]受欢迎的牛 题目描述 每头奶牛都梦想成为牛棚里的明星.被所有奶牛喜欢的奶牛就是一头明星奶牛.所有奶 牛都是自恋狂,每头奶牛总是喜欢自己的.奶牛之间的"喜欢&q ...