首页 » 编写高质量代码:改善JavaScript程序的188个建议 » 编写高质量代码:改善JavaScript程序的188个建议全文在线阅读

《编写高质量代码:改善JavaScript程序的188个建议》建议31:使用迭代

关灯直达底部

任何可以用递归实现的算法都可以用迭代实现。迭代算法通常包括几个不同的循环,分别对应算法过程的不同方面。虽然迭代也会导致性能问题,但是使用优化的循环替代长时间运行的递归函数可以提高性能,因为运行一个循环比反复调用一个函数的开销要低。

例如,合并排序算法是最常用的以递归实现的算法。下面是一个简单的合并排序算法:


function merge(left,right){

var result=;

while(left.length>0&&right.length>0){

if(left[0]<right[0]){

result.push(left.shift);

}else{

result.push(right.shift);

}

}

return result.concat(left).concat(right);

}

function mergeSort(items){

if(items.length==1){

return items;

}

var middle=Math.floor(items.length/2),left=items.slice(0,middle),right=items.slice(middle);

return merge(mergeSort(left),mergeSort(right));

}


这个合并排序代码相当简单直接,其中mergeSort函数被调用得非常频繁。对一个超过1500项的数组进行操作,就可能在Firefox上导致栈溢出。程序陷入栈溢出错误并不一定要修改整个算法,这说明递归不是最好的实现方法。合并排序算法还可以用迭代实现,例如:


function mergeSort(items){

if(items.length==1){

return items;

}

var work=;

for(var i=0,len=items.length;i<len;i++){

work.push([items[i]]);

}

work.push();

for(var lim=len;lim>1;lim=(lim+1)/2){

for(var j=0,k=0;k<lim;j++,k+=2){

work[j]=merge(work[k],work[k+1]);

}

work[j]=;

}

return work[0];

}


在上面代码中,mergeSort实现与上一个merge函数同样的功能却没有使用递归。虽然迭代可能比递归合并排序慢一些,但是它不会像递归那样影响调用栈。将递归算法切换为迭代是避免栈溢出错误的方法之一。