zoukankan      html  css  js  c++  java
  • 尾递归

    一、什么是尾调用?

    尾调用的概念非常简单,一句话就能说清楚,就是指某个函数的最后一步是调用另一个函数。

    function f(x){
      return g(x);
    }

    二、尾调用优化

    函数在调用的时候会在调用栈(call stack)中存有记录,每一条记录叫做一个调用帧(call frame),每调用一个函数,就向栈中push一条记录,函数执行结束后依次向外弹出,直到清空调用栈,参考下图:

    function foo () { console.log(111); }
    function bar () { foo(); }
    function baz () { bar(); }
    
    baz();
    call stack

    造成这种结果是因为每个函数在调用另一个函数的时候,并没有 return 该调用,所以JS引擎会认为你还没有执行完,会保留你的调用帧。

    如果对上面的例子做如下修改:

    function foo () { console.log(111); }
    function bar () { return foo(); }
    function baz () { return bar(); }
    
    baz();

    二、什么是尾递归?

    前面我们知道了尾调用的概念,当一个函数尾调用自身,就叫做尾递归。

    function foo () {
        return foo();
    }

    那么尾递归相比递归而言,有哪些不同呢?
    我们通过下面这个求阶乘的例子来看一下:

    function factorial (num) {
        if (num === 1) return 1;
        return num * factorial(num - 1);
    }
    
    factorial(5);            // 120
    factorial(10);           // 3628800
    factorial(500000);       // Uncaught RangeError: Maximum call stack size exceeded

    如果用尾递归来计算阶乘呢?

    'use strict';
    
    function factorial (num, total) {
        if (num === 1) return total;
        return factorial(num - 1, num * total);
    }
    
    factorial(5, 1);                // 120
    factorial(10, 1);               // 3628800
    factorial(500000, 1);           // 分情况
    
    
    
    ps:值得注意的是,虽然说这里启用了严格模式,但是经测试,在Chrome和Firefox下,还是会报栈溢出错误,并没有进行尾调用优化
    Safari浏览器进行了尾调用优化,factorial(500000, 1)结果为Infinity,因为结果超出了JS可表示的数字范围
    如果在node v6版本下执行,需要加--harmony_tailcalls参数,node --harmony_tailcalls test.js
    node最新版本已经移除了--harmony_tailcalls功能

    博主试了一下,下面这个函数,最多可以到 12578 次递归
    function F(n) {
      if (n>12577) return n;
      return F(n+1);
    }


  • 相关阅读:
    A Simple Problem with Integers poj 3468 多树状数组解决区间修改问题。
    Fliptile 开关问题 poj 3279
    Face The Right Way 一道不错的尺取法和标记法题目。 poj 3276
    Aggressive cows 二分不仅仅是查找
    Cable master(二分题 注意精度)
    B. Pasha and String
    Intervals poj 1201 差分约束系统
    UITextField的快速基本使用代码块
    将UIImage转换成圆形图片image
    color转成image对象
  • 原文地址:https://www.cnblogs.com/amiezhang/p/10143067.html
Copyright © 2011-2022 走看看