加速程序计算优化技术---记忆

在计算机领域,记忆是主要用于加速程序计算的一种优化技术,它使得函数避免重复演算之前已被处理的输入,而返回已缓存的结果。

JS的对象和数组要实现这种优化是非常方便的。

下面用一个经典递归函数----斐波那契数列

var conut=0;

var fibonaccii = function (n)

{     conut++;

       console.log("conut:" + conut);

       return n< 2 ? n : fibonaccii(n-1) + fibonaccii(n-2);

};

function test() {

       for (var i= 0; i <= 10; i += 1) {

              console.log(i+":" + fibonaccii(i));

       }

}

这样工作是可行的;但是效率非常低。我算了一下:

spacer.gif

函数被调用了453次,我们调用了11次;所以,它自身递归调用442次,有很多是已经被刚刚计算过了;如果我们让函数具有记忆功能,就可以显著提高极少计算量,提高效率。

var count = 0;

var fibonaccii = function () {

      

       var memo =[0,1];

       var fib =function (n) {

              count++;

              console.log("count:" + count);

              varresult = memo[n];

              if(typeofresult !== 'number') {

                     result= fib(n-1) + fib(n-2);

                     memo[n]= result;

              }

              returnresult;

       };

       returnfib;

}();

function test() {

       for (var i= 0; i <= 10; i += 1) {

              console.log(i+":" + fibonaccii(i));

       }

}

test();

spacer.gif

这个函数返回同样的结果,但是很明显,仅仅被调用了29次,我们自己调用了11次;也就只用了18次去取之前存储的结果;

 

 

当然,我们可以推而广之,编写一个函数来帮助,我们构造带记忆功能的函数,memoizer函数取得一个初始的memo数组和formua函数;它返回一个管理memo存储和在需要时调用fromula的函数recur;我们把这个函数recur函数和它的参数传递给formula函数

 

var memoizer = function (memo, formula) {

       var recur= function (n) {

              varresult = memo[n];

              if(typeofresult !== 'number') {

                     result= formula(recur, n);

                     memo[n]= result;

              }

              returnresult;

       }

       returnrecur;

};

现在,我们可以使用memoizer函数来定义fibonaccii函数,提供其初始的memo数组和formula函数;

var fibonaccii = memoizer([0,1],function (recur, n)) {

       returnrecur(n - 1) + recur(n - 2);

});

 

通过这种设计方案,产生另一个函数的函数,极大地减少了我们工作量,例如,我们要产生一个记忆的阶乘函数,我们可以这样

var factorial = memoizer([0, 1], function (recur, n)){

       returnn*recur(n - 1);

}

只需要提供基本的阶乘公式就可以了。