递归我们不陌生,

  那什么是尾递归呢?

  为什么要用尾递归呢?

  尾递归怎么用呢?

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

我们知道递归非常耗费内存,一不小心就会发生‘栈溢出’, 相信你一定遇到过这个错误: 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. css 盒子下

    1.padding 有小属性 padding-top: 30px; padding-right: 30px; padding-bottom: 30px; padding-left: 30px; 小属性 ...

  2. MP的自动填充功能

    用来进行自动填充时间. 使用注解@TableTield(fill=FieldFill.insert)插入时进行性填充 使用注解@TableTield(fill=FieldFill.Update)更新时 ...

  3. 201871010107-公海瑜《面向对象程序设计(java)》第十四周学习总结

    201871010107-公海瑜<面向对象程序设计(java)>第十四周学习总结             项目                            内容   这个作业属于 ...

  4. Appium+python自动化(二)- 环境搭建—下(超详解)

    简介 宏哥的人品还算说得过去,虽然很久没有搭建环境了,但是换了新电脑设备,一气呵成,将android的测试开发环境已经搭建准备完毕.上一篇android测试开发环境已经准备好, 那么接下来就是appi ...

  5. 重拾算法之复杂度分析(大O表示法)

    .katex { display: block; text-align: center; white-space: nowrap; } .katex-display > .katex > ...

  6. ifream

    很早前看到一个说法,前端要尽量少用ifream,因为它让页面调试麻烦,互操作不方便,会增加http请求,重复加载资源导致内存增加,产生多个页面不好管理等等. 所以很多标准的设计中都推荐不要用ifrea ...

  7. CF1175F The Number of Subpermutations

    题目链接 题意 给出一个长度为\(n\)的序列\(a\),问有多少个区间\([l,r]\)满足:在区间\([l,r]\)内,\([1,r-l+1]\)的每个整数都恰好出现了一次. \(n \le 3 ...

  8. tecplot无法处理高版本fluent导出的Ensight格式

    高版本的Fluent完成计算,将计算结果导出为Ensight格式,然后再导入tecplot当中进行后处理的时候会遇见如下的错误: 但是将低版本的Fluent计算结果导出为Ensight格式,却可以顺利 ...

  9. 企业级Nginx负载均衡与keepalived高可用实战(二)keepalived篇

    1.Keepalived高可用软件 1.1.Keepalived介绍 Keepalived软件起初是专门为LVS负载均衡软件设计的,用来管理并监控LVS集群系统中各个服务节点的状态,后来又加入了可以实 ...

  10. html5手机端播放音效不卡的方法

    html5手机端播放音效不卡的方法线下载http://wxserver.knowway.cn/solosea/js/audioEngine.js 这个是性能不错 然后直接播放音效就可以了 audioE ...