Thinking in scala (4)----阶乘与尾递归

时间:2022-12-04 19:32:47

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. 用C++的类做三种优先队列的实现

    学过数据结构的都知道优先队列这种东西,普通的队列是依据入队顺序,先入队的先出队,而优先队列则是依照键值,键值越大(或越小),就越先出队. 所以,优先队列基本支持push,pop,empty,size, ...

  2. CoreAnimation1-图层树、寄宿图以及图层几何学

    (一)图层的树状结构 Core Animation其实是一个令人误解的命名.你可能认为它只是用来做动画的,但实际上它是从一个叫做Layer Kit这么一个不怎么和动画有关的名字演变而来,所以做动画这只 ...

  3. Java基础练习2(构造方法)

    1.以下关于面向对象概念的描述中,不正确的一项是() A.在构造方法中,this()只能出现在构造方法第一行位置 B.在构造方法中,super()只能出现在构造方法第一行位置 C.this()和sup ...

  4. scala时间和时间戳互转

    时间转换为时间戳: import java.text.SimpleDateFormat object test { def main(args: Array[String]): Unit = { va ...

  5. Eclipse常用20个快捷键

    Eclipse常用20个快捷键 1. Ctrl+F : 本文查找Find与替换Replace 2. Ctrl+H : 全局搜索,可按照文件类型搜索 3. Ctrl+1 : 快速修复,能快速的显示光标所 ...

  6. Haskell复习笔记(一)

    Haskell笔记这是第三次总结,前两次都因为各种原因丢失了,对于Haskell我算不上什么大神,只不过在大学时为了学习算法时选择了Haskell. 当时的入门书籍选择的是<Learn You ...

  7. springboot 使用JPA自动生成Entity实体类的方法

    1. 2. 3.添加数据库 4. 5. 6. 7.点击OK完成. 8.去掉红色波浪线方法. 9.配置数据源 完成!

  8. hadoop之 hadoop能为企业做什么?

    hadoop是什么? Hadoop是一个开源的框架,可编写和运行分不是应用处理大规模数据,是专为离线和大规模数据分析而设计的,并不适合那种对几个记录随机读写的在线事务处理模式.Hadoop=HDFS( ...

  9. 三角形垂点坐标js算法&lpar;三点定圆求圆心&rpar;

    已知平面三点坐标A(x1, y1).B(x2, y2).C(x3, y3),三点定圆也就是三角形的中垂线交点, //平面三点定位算法 function locate(x1, y1, x2, y2, x ...

  10. 前端-关于 Vue 和 React 区别的一些笔记

    监听数据变化的实现原理不同 1.Vue 通过 getter/setter 以及一些函数的劫持,能精确知道数据变化,不需要特别的优化就能达到很好的性能 2.React 默认是通过比较引用的方式进行的,如 ...