排序算法——归并排序

思路

我学习的归并是简单的二路归并,思路如下:

① 将数组平均分成两份

② 递归重复①,直到每个数组中只有1个元素,只有一个元素的数组可以认为是排好序的

③ 将两个排好序的数组合并成一个排好序的数组

④ 重复③直到最终得到一个排好序的数组

javascript实现

/**
 * 归并排序
 * @param arr
 * @returns 
 */
function mergeSort(arr){
    if(!(arr instanceof  Array)){
        return [];
    }
    if(arr.length<=1){
        return arr;
    }

    var left=arr.splice(0,Math.floor(arr.length/2)),
        right=arr,
        res=[];
    left=mergeSort(left);
    right=mergeSort(right);
    //一次归并,认为左右两边的数组是排序好的,通过这种方式将它们合成为一个排序好的数组
    //只有一个元素的数组可以认为是已经排序好的,所以通过:
    //left=mergeSort(left);
    //right=mergeSort(right);
    //两步递归得到拆分为一个元素的数组,再通过下面的归并得到结果
    while(left.length && right.length){
        left[0]>right[0] ? res.push(right.shift()): res.push(left.shift());
    }
    //归并剩下的元素都是比res中的大的,直接拼接到后边就好了
    res=res.concat(left,right);
    return res;
}

其他

在一些文章里边看到有人认为浏览器中,采用递归函数调用的方式实现算法有栈溢出的风险。

因为函数每次调用都会产生一个上下文,放在上下文栈中,执行完毕后才会清除。但是递归调用会导致很多个上下文对象,这样如果待排序的数组过长,在某些浏览器下可能会发生栈溢出的错误。

测试浏览器上下文栈上限的代码:

var cnt = 0;
try {
  (function() {
    cnt++;
    arguments.callee();
  })();
} catch(e) {
  console.log(e.message, cnt);
}

我测试过后发现主流浏览器的上下文栈长度上限都能达到2w左右,在前端一般不会做如此大量数据的排序。

也可以选择将递归的方式改为迭代的方式来规避这个问题

posted @ 2015-10-12 13:44  桃子夭夭  阅读(386)  评论(0编辑  收藏  举报