二路归并排序主要运用了“分治算法”,分治算法就是将一个大的问题划分为n个规模较小而结构相似的子问题。
这些子问题解决的方法都是类似的,解决掉这些小的问题之后,归并子问题的结果,就得到了“大”问题的解。
二路归并排序主旨是“分解”与“归并”。
下面是参考《高性能JavaScript》中的代码:
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(arr){ if(arr.length==1) {return arr}; var mid=Math.floor(arr.length/2); var left_arr=arr.slice(0,mid),right_arr=arr.slice(mid); return merge(mergeSort(left_arr),mergeSort(right_arr)); }
这段代码很简单易懂,但是容易出现栈溢出错误。此时我们可以更改mergeSort()函数,用迭代的方式来实现,代码如下所示:
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()函数功能与前例相同,但是没有使用递归。把递归算法改用迭代实现是避免栈溢出的错误方法之一。