递归我们不陌生,

  那什么是尾递归呢?

  为什么要用尾递归呢?

  尾递归怎么用呢?

  带着这三个问题我们来了解它,

我们知道递归非常耗费内存,一不小心就会发生‘栈溢出’, 相信你一定遇到过这个错误: stack overflow,

尾递归就是用来优化递归的这个问题的。

  尾递归的定义: 在函数的最后一步返回自身,也就是显示地return自身就称为尾递归。对于尾递归来说,

由于只存在一个调用帧,所以永远不会发生‘栈溢出’。

  我们来举例说明尾递归的好处:

  • 比如计算n的阶乘, 我们首先想到找规律, n的阶乘等于n* (n-1)的阶乘
  • 找出口1的阶乘等于1
  • 然后我们就很自然的用递归写出
  • function jieCheng(n) {
    if (n===1) {
    return 1
    }
    return n * jieCheng(n -1);
    }
    const result = jieCheng(5); console.log(result); //

    很自然, so easy有木有,

   but,  这样我们每递归一次,上一次的调用记录还保存着, 也就是说我们计算n的阶乘最多要保存n个调用记录,复杂度为O(n).

   改成尾递归:

   

function weiJieCheng(n, total=1) {
if (n === 1) {
return total;
}
return weiJieCheng(n-1, n * total);
} console.log(weiJieCheng(5), 'wei'); //

  把中间变量改写成函数的参数, 这样就只保存了一个调用记录,复杂度为O(1)。

  再用蹦床函数对尾递归进行优化,把递归执行转换成循环执行:

function trampoline(f) {
while(f && f instanceof Function) {
f = f ();
}
}
trampoline(weiJieCheng(5, 1))

ES6 入门系列 (三) 尾递归的更多相关文章

  1. ES6入门系列三(特性总览下)

    0.导言 最近从coffee切换到js,代码量一下子变大了不少,也多了些许陌生感.为了在JS代码中,更合理的使用ES6的新特性,特在此对ES6的特性做一个简单的总览. 1.模块(Module) --C ...

  2. mybatis入门系列三之类型转换器

    mybatis入门系列三之类型转换器 类型转换器介绍 mybatis作为一个ORM框架,要求java中的对象与数据库中的表记录应该对应 因此java类名-数据库表名,java类属性名-数据库表字段名, ...

  3. C# 互操作性入门系列(三):平台调用中的数据封送处理

    好文章搬用工模式启动ing ..... { 文章中已经包含了原文链接 就不再次粘贴了 言明 改文章是一个系列,但只收录了2篇,原因是 够用了 } --------------------------- ...

  4. [转]C# 互操作性入门系列(三):平台调用中的数据封送处理

    参考网址:https://www.cnblogs.com/FongLuo/p/4512738.html C#互操作系列文章: C# 互操作性入门系列(一):C#中互操作性介绍 C# 互操作性入门系列( ...

  5. ActiveMQ入门系列三:发布/订阅模式

    在上一篇<ActiveMQ入门系列二:入门代码实例(点对点模式)>中提到了ActiveMQ中的两种模式:点对点模式(PTP)和发布/订阅模式(Pub & Sub),详细介绍了点对点 ...

  6. ES6 入门系列 - 函数的扩展

    1函数参数的默认值 基本用法 在ES6之前,不能直接为函数的参数指定默认值,只能采用变通的方法. function log(x, y) { y = y || 'World'; console.log( ...

  7. ES6入门系列四(测试题分析)

    0.导言 ES6中新增了不少的新特性,来点测试题热热身.具体题目来源请看:http://perfectionkills.com/javascript-quiz-es6/. 以下将一题一题来解析what ...

  8. ES6 入门系列 - let 和 const 命令

    let命令 基本用法 ES6新增了let命令,用来声明变量.它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效. { let a = ; ; } a // ReferenceEr ...

  9. ES6 入门系列 (一)ES6的前世今生

    要学好javascript , ECMAScript标准比什么都强, ESMAScript标准已经用最严谨的语言和最完美的角度展现了语言的实质和特性. 理解语言的本质后,你已经从沙堆里挑出了珍珠,能经 ...

随机推荐

  1. E07【餐厅】What would you recommend?

    核心句型 What would you recommend? 你有什么推荐吗? 场景对话: A:What do  you  want  to  eat? 你想吃点什么? B:I don't know. ...

  2. SQL-on-Hadoop 技术

    SQL-on-Hadoop 技术 备注 Apache Hive Cloudera Impala Facebook Presto Apache Drill Spark SQL Apache Phoeni ...

  3. 【视频技术】ffmpeg截取图片(Mac)

    1. 输出单张图片:ffmpeg -i NLP-CNN.mp4 -f image2 -ss 2000 -vframes 1 -s 220*220 NLP-CNN-003.jpg 2. 输出所有图片: ...

  4. 18-numpy笔记-莫烦pandas-6-plot显示

    代码 import pandas as pd import numpy as np import matplotlib.pyplot as plt data = pd.Series(np.random ...

  5. VMware10新建虚拟机

    1. 新建虚拟机 2. 选择 “典型(推荐)(T)” 安装 3. “稍后安装操作系统”,创建一个空白硬盘 4. 选择 “Linux” 的 “CentOS 64位” 5. 设置 “虚拟机名称” 和 “位 ...

  6. 【使用篇二】SpringBoot整合Listener(3)

    两种方式: 通过注解扫描完成 Listener 组件的注册 通过方法完成 Listener 组件注册 一.通过注解扫描完成 Listener 组件的注册 1. 编写Listener类 /*** spr ...

  7. null与“ ”的区别

    null是空对象,""是空字符串 null可以赋值给任何对象 ""只能赋值给字符串对象 String s=null; string.trim()就会抛出为空的e ...

  8. Java System.getProperty vs System.getenv

    转自:https://www.baeldung.com/java-system-get-property-vs-system-getenv 1. Introduction The package ja ...

  9. 0x00 Wechall writeup

    目录 0x00 Wechall writeup Training: Get Sourced Training: ASCII Encodings: URL Training: Stegano I Tra ...

  10. Linux性能优化实战学习笔记:第十五讲

    一.内存映射 内存管理也是操作系统最核心的功能之一,内存主要用来存储系统和应用程序的指令.数据.缓存等 1.我们通说的内存指的是物理内存还是虚拟内存? 我们通常说的内存容量,其实这指的是物理内存,物理 ...