code1:

object factorial{
  def main(args:Array[String])={
    println(factorial(args(0).toInt))
  }

  def factorial(x:Int):Int =
    if (x==0) 1 else x * factorial(x-1)
}

这个实现的执行过程如下,比如我们计算4的阶乘factorial(4)

factorial(4)

--> if (4==0) 1 else 4 * factorial(4-1)

-->4*factorial(3)

-->4*(3*factorial(2))

-->4*(3*(2*factorial(1)))

-->4*(3*(2*(1*factorial(0))))

-->4*(3*(2*(1*1)))

-->24

计算机在执行上述计算的过程中,需要用到“栈”,并且我们不难看到为了计算factorial(4),栈不断增大。

为了避免像这样的计算可能导致“栈溢出”,可以采用一个小技巧,就是将上述的递归转化为“尾”递归。

关于尾递归,可以参考:http://en.wikipedia.org/wiki/Tail_call

code2:

object factorial{
  def main(args:Array[String])={
    println(factorial(args(0).toInt,1))
  }

  def factorial(x:Int,result:Int):Int =
    if (x==0) result else factorial(x-1,x*result)
}

思路也很简单,不再赘述。

但是code2有个缺点,那就是factorial函数的参数多了一个:result,并且,每次调用factorial函数,都要给result传一个实参:1

因为将code2修改如下:

code3:

object factorial{
  def main(args:Array[String])={
    println(factorial(args(0).toInt))
  }

  def factorial(x:Int):Int ={
     def loop(x:Int,acc:Int):Int = {
       if(x==0) acc
       else loop(x-1,x*acc)
     }
     loop(x,1)
  }
}

The End..........

Thinking in scala (4)----阶乘与尾递归的更多相关文章

  1. Scala进阶之路-尾递归优化

    Scala进阶之路-尾递归优化 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 递归调用有时候能被转换成循环,这样能节约栈空间.在函数式编程中,这是很重要的,我们通常会使用递归方法来 ...

  2. Java8之旅(六) -- 使用lambda实现尾递归

    前言 本篇介绍的不是什么新知识,而是对前面讲解的一些知识的综合运用.众所周知,递归是解决复杂问题的一个很有效的方式,也是函数式语言的核心,在一些函数式语言中,是没有迭代与while这种概念的,因为此类 ...

  3. Scala详解

    1       快速入门... 4 1.1             分号... 4 1.2             常变量声明... 4 1.2.1         val常量... 4 1.2.2  ...

  4. Java8函数之旅 (六) -- 使用lambda实现Java的尾递归

    前言 本篇介绍的不是什么新知识,而是对前面讲解的一些知识的综合运用.众所周知,递归是解决复杂问题的一个很有效的方式,也是函数式语言的核心,在一些函数式语言中,是没有迭代与while这种概念的,因为此类 ...

  5. Scala总结

    Scala总结 ===概述 scala是一门以Java虚拟机(JVM)为目标运行环境并将面向对象和函数式编程的最佳特性结合在一起的静态类型编程语言. scala是纯粹的面向对象的语言.java虽然是面 ...

  6. Scala学习十五——注解

    一.本章要点 可以为类.方法.字段.局部变量.参数.表达式.类型参数以及各种类型定义添加注解 对于表达式和类型,注解跟在被注解的条目之后 注解的形式有@Annotation.@Annotation(v ...

  7. scala编程(八)——函数和闭包

    当程序变得庞大时,你需要一些方法把它们分割成更小的,更易管理的片段.为了分割控制流,Scala 提供了所有有经验的程序员都熟悉的方式:把代码分割成函数.实际上,Scala 提供了许多 Java 中没有 ...

  8. 递归、尾递归和使用Stream延迟计算优化尾递归

    我们在学数据结构的时候必然会接触栈(Stack),而栈有一个重要的应用是在程序设计语言中实现递归.递归用途十分广泛,比如我们常见的阶乘,如下代码: 1234 public static int (in ...

  9. Android ViewTreeObserver简介

    Android ViewTreeObserver简介   一.结构 public final class ViewTreeObserver extends Object java.lang.Objec ...

随机推荐

  1. 解决IOS safari在input focus弹出输入法时不支持position fixed的问题

    该文章为转载 我们在做移动web应用的时候,常常习惯于使用position:fixed把一个input框作为提问或者搜索框固定在页面底部.但在IOS的safari和webview中,对position ...

  2. HDU1171--Big Event in HDU(多重背包)

    Big Event in HDU   Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...

  3. 学习笔记——抽象工厂模式Abstract Factory

    在工厂模式的基础上,通过为工厂类增加接口,实现其他产品的生产,而不用一类产品就增加一个工厂. 依然以<真菌世界>游戏故事类比,树作为工厂,如果现在有两类树,一类生产快速弄真菌飞机和20毫米 ...

  4. 未能加载文件或程序集 Microsoft.VisualBasic.PowerPacks.Vs, Version=10.0.0.0 解决 亲测

    项目打开winform程序做的某些窗体时报错: ************* 异常文本 ************** System.Reflection.TargetInvocationExceptio ...

  5. EtherChannel Cisco 端口聚合详解

    冗余连接及其实现 无论什么设备都无法保障运行的绝对稳定性,即使再优秀的产品也无法保证24×7不间断的工作.除去设备或模块损坏.传输线路中断等硬件故障原因以外,还可能由于网络流量过载.任务负荷过大而导致 ...

  6. 2的幂次方(power)

    2的幂次方(power) 题目描述 任何一个正整数都可以用2的幂次方表示.例如:137=27+23+20同时约定方次用括号来表示,即ab 可表示为a(b). 由此可知,137可表示为:2(7)+2(3 ...

  7. 使用jquery模拟键盘事件,但window系统并不会真的响应事件,只是浏览器当前页面会响应而已

    <!DOCTYPE html> <html> <head> <title>Demo</title> <meta http-equiv= ...

  8. IE6 7 父级元素的overflow:hidden 是包不住子级的relative

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  9. 转 Android网络编程之使用HttpClient批量上传文件 MultipartEntityBuilder

    请尊重他人的劳动成果,转载请注明出处:Android网络编程之使用HttpClient批量上传文件 http://www.tuicool.com/articles/Y7reYb 我曾在<Andr ...

  10. 如何删除要素类 IFeatureWorkspace 接口介绍(1)

    如何删除要素类 要想删除一个要素类,那么必须先得到这个,在得到这个要素类的时候,我们要学习一个新的接口IFeatureWorkspace. IFeatureWorkspace  接口介绍 这个接口主要 ...