函数可以通过用对象去记住先前操作的结果,从而避免无谓的运算,这种优化称为 记忆(Memoization).
1、求数字之和基本递归方法
其中fibonacci为一般常用的递归方法,能满足基本要求,但存在重复调用的现象
var count =0;//记录遍历次数 var fibonacci = function(n){ count++; return n<2 ? n:fibonacci(n-1)+fibonacci(n-2); } //遍历11次后fibonacci()被调用了453次 ,我们调用了11次 function menoizationMethod1(){ var htmlStr = ""; for ( var i = 0; i <=10; i++) { var tmp_count = count; htmlStr +="参数值:"+i+"\t和:"+fibonacci(i)+"\t该参数值下遍历次数:"+ (count-tmp_count)+"\t累计遍历次数:"+count+"<br/>"; } document.getElementById("memoization1").innerHTML = htmlStr; count = 0; }
<button onclick="menoizationMethod1();">传统递归</button> <div id='memoization1'></div>
?2、求数字之和(同过记忆优化递归方法)
var count =0;//记录遍历次数 var fibonacci2 =function(){ var memo = [0,1]; var fib = function(n){ var result = memo[n]; count++; if(typeof result !== 'number'){ result = fib(n-1) + fib(n-2); memo[n] = result; } return result; } return fib; }(); //遍历11次后fibonacci()被调用了29次 ,我们调用了11次 function menoizationMethod2(){ var htmlStr = ""; for ( var i = 0; i <=10; i++) { var tmp_count = count; htmlStr +="参数值:"+i+"\t和:"+fibonacci2(i)+"\t该参数值下遍历次数:"+ (count-tmp_count)+"\t累计遍历次数:"+count+"<br/>"; } document.getElementById("memoization2").innerHTML = htmlStr; count = 0; }
<button onclick="menoizationMethod2();">记忆递归</button> <div id='memoization2'></div>
3、形式一般化
//此类函数形式一般化 var count =0;//记录遍历次数 var memoizer = function (memo,fundamenta1){ var shell = function(n){ count++; var result = memo[n]; if(typeof result !== 'number'){ result = fundamenta1(shell,n); memo[n] = result; } return result; } return shell; } //计算数字累积和 function memoizerSumMethod(){ var htmlStr = ""; var fib1 = memoizer([0,1],function(shell,n){ return shell(n-1)+shell(n-2); }); for ( var i = 0; i <=10; i++) { var tmp_count = count; htmlStr +="参数值:"+i+"\t和:"+fib1(i)+"\t该参数值下遍历次数:"+ (count-tmp_count)+"\t累计遍历次数:"+count+"<br/>"; } document.getElementById("memoization3").innerHTML = htmlStr; count = 0; } //计算数字乘积(阶乘) function memoizerMultiplyMethod(){ var htmlStr = ""; var fib2 = memoizer([1,1],function(shell,n){ return n*shell(n-1); }); for ( var i = 0; i <=10; i++) { var tmp_count = count; htmlStr +="参数值:"+i+"\t乘积:"+fib2(i)+"\t该参数值下遍历次数:"+ (count-tmp_count)+"\t累计遍历次数:"+count+"<br/>"; } document.getElementById("memoization4").innerHTML = htmlStr; count = 0; }
?
<button onclick="memoizerSumMethod();">计算数字累积和</button> <div id='memoization3'></div> <button onclick="memoizerMultiplyMethod();">计算数字累积和</button> <div id='memoization4'></div>
?