scala-尾递归
------------------------- by chenkh -----------------------------
随笔记录什么是尾递归,为什么需要尾递归,尾递归show by example。
0,前言
递归通过灵巧的函数定义,告诉计算机做什么。在函数式编程中,随处可见递归思想的运用。一个递归的经典例子:
- //递归快排
- def quicksort(ls: List[Int]):List[Int] = {
- if(ls.isEmpty)
- ls
- else
- quicksort(ls.filter(_ < ls.head)) ::: ls.head :: quicksort(ls.filter(_ > ls.head))
- //quicksort(ls.filter(x => x < ls.head)) ::: ls.head :: quicksort(ls.filter(x => x > ls.head))
- }
我们以上面代码最后一个快速排序函数为例,使用递归的方式,其代码实现非常的简洁和通俗易懂。递归函数的核心是设计好递归表达式,并且确定算法的边界条件。上面的快速排序中,认为空列表就是排好序的列表,这就是递归的边界条件,这个条件是递归终止的标志。
1,什么是尾递归?
尾递归本质上仍然是一种递归,可以看做是普通递归方法的改进。
尾递归是指递归调用是函数的最后一个语句,而且其结果被直接返回,这是一类特殊的递归调用。由于递归结果总是直接返回, 尾递归比较方便转换为循环 ,因此编译器容易对它进行优化。
2,为什么需要尾递归?
递归算法需要保持调用堆栈,效率较低,如果调用次数较多,会耗尽内存或栈溢出。然而,尾递归可以克服这一缺点。
3,show by factorial
- //递归阶乘
- def factorial(n: BigInt): BigInt = {
- if(n <=1) 1 else n * factorial(n-1)
- }
- //尾递归阶乘
- def factorialTailRecursive(n: BigInt): BigInt = {
- def _loop(acc: BigInt, n: BigInt): BigInt = if(n <=1) acc else _loop(acc*n, n-1)
- _loop(1, n)
- }
- /*
- 我们发现,由于每次递归调用n-1的阶乘时,都有一次额外的乘法计算,这使得堆栈中的数据都需要保留。在新的递归中要分配新的函数栈。
- factorial(4)
- --------------
- 4 * factorial(3)
- 4 * (3 * factorial(2))
- 4 * (3 * (2 * factorial(1)))
- 4 * (3 * (2 * 1))
- 而尾递归在效率上和循环是等价的,该函数中的 _loop 在最后一步,要么返回递归边界条件的值,要么调用递归函数本身。
- factorialTailRecursive(4)
- --------------------------
- _loop(1, 4)
- _loop(4, 3)
- _loop(12, 2)
- _loop(24, 1)
- */
改写成尾递归版本的关键:
尾递归版本最重要的就是找到合适的累加器,该累加器可以保留最后一次递归调用留在堆栈中的数据,积累之前调用的结果,这样堆栈数据就可以被丢弃,当前的函数栈可以被重复利用。
在这个例子中,变量acc就是累加器,每次递归调用都会更新该变量,直到递归边界条件满足时返回该值。
对于尾递归,Scala语言特别增加了一个注释 @tailrec
,该注释可以确保程序员写出的程序是正确的尾递归程序,如果由于疏忽大意,写出的不是一个尾递归程序,则编译器会报告一个编译错误,提醒程序员修改自己的代码。
scala-尾递归的更多相关文章
- Scala尾递归
递归函数应用 首先,我们来对比两个递归方法的求值步骤. 假设有方法gcd,用来计算两个数的最大公约数.下面是欧几里得算法的实现: def gcp(a: Int, b: Int): Int = if ( ...
- 【Scala】尾递归优化
以递归方式思考 递归通过灵巧的函数定义,告诉计算机做什么.在函数式编程中,随处可见递归思想的运用.下面给出几个递归函数的例子: object RecursiveExample extends App{ ...
- Scala Tail Recursion (尾递归)
Scala对尾递归进行了优化,甚至提供了专门的标注告诉编译器需要进行尾递归优化.不过这种优化仅限于严格的尾递归,间接递归等情况,不会被优化. 尾递归的概念 递归,大家都不陌生,一个函数直接或间接的调用 ...
- Scala进阶之路-尾递归优化
Scala进阶之路-尾递归优化 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 递归调用有时候能被转换成循环,这样能节约栈空间.在函数式编程中,这是很重要的,我们通常会使用递归方法来 ...
- Scala 经典的模式匹配和尾递归
Scala 经典的模式匹配和尾递归 package io import java.io.{BufferedWriter, File, FileWriter} import java.text.Simp ...
- Thinking in scala (4)----阶乘与尾递归
code1: object factorial{ def main(args:Array[String])={ println(factorial(args(0).toInt)) } def fact ...
- scala通过尾递归解析提取字段信息
一.背景 获取数据中以“|”作为字段间的分隔符,但个别字段中数据也是以“|”作为分隔符.因此,在字段提取时需要保护数据完整性. 二.实现 1.数据以“|”分隔,可以采用递归方式迭代解析.通过尾递归方式 ...
- scala实战学习-尾递归函数
求 $$ \Sigma\sideset{^b_a}f(x) $$ object sumfunc{ def sum(f: Int => Int)(a: Int)(b:Int): Int = { @ ...
- Scala 的确棒
我的确认为计算机学院应该开一门 Scala 的语言课程. 在这篇文章中,我会讲述为什么我会有这样的想法,在此之前,有几点我想要先声明一下: 本文无意对编程语言进行评比,我要讲述的主体是为什么你应该学习 ...
- Scala HandBook
目录[-] 1. Scala有多cool 1.1. 速度! 1.2. 易用的数据结构 1.3. OOP+FP 1.4. 动态+静态 1.5. DSL 1.6 ...
随机推荐
- pythonbrew, pythonz, virtualenv
Python 的虛擬環境及多版本開發利器─Virtualenv 與 Pythonbrewhttp://www.openfoundry.org/tw/tech-column/8516-pythons-v ...
- java动态绑定的一点注意
动态绑定只是针对对象的方法,对于属性无效.因为属性不能被重写. show me code: public class Father{ public String name = "父亲属性&q ...
- es6 class
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...
- AndroidUI设计之布局-详细解析布局实现
写完博客的总结 : 以前没有弄清楚的概念清晰化 父容器与本容器属性 : android_layout...属性是本容器的属性, 定义在这个布局管理器的LayoutParams内部类中, 每个布局管理器 ...
- jquery mobile 登陆后页面验证
调用 pagebeforechange方法 $(document).bind("pagebeforechange", function (e, data) { if (typeof ...
- Converter转换器使用
package com.xu.javabean; import java.lang.reflect.InvocationTargetException; import java.util.Date; ...
- oracle免客户端安装 plsql连接
开发的过程中,往往没有必要在自己的电脑上安装oracle,也实在太大了. 这里介绍一种使用plsql连接oracle的方法,类似于navicat之连接mysql. 先下载plsql,进行安装,这里提供 ...
- sftp自动授权登录
客户的账号下执行 ssh-keygen -t rsa 生成秘钥文件 ~/.ssh/id_rsa --秘钥文件 ~/.ssh/id_rsa.pub --公钥文件 将公钥文件id_rsa.pub放到sft ...
- 读取数据库的表并绑定到Listview
$aResultEventlog = _GetQueryTable($strSQL_Compare_FailRecordEventIDs, $iRowsEventlog, $iColsEventlog ...
- .net 中select和where的区别
Select(p=>p.ID==id) 这里选择的结果是通过p,访问迭代器,然后选取的是p.ID==id的结果,选择到的是bool对象 Where(p=>p.ID==id) 这里是过滤,p ...