日期:2014-05-16  浏览次数:20347 次

Js中通过记忆来优化递归方法

函数可以通过用对象去记住先前操作的结果,从而避免无谓的运算,这种优化称为 记忆(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>

?