从零开始学算法 - 归并排序

归并的思路:将大问题拆解成小问题,小问题单独解决后,再合并成大问题。

翻译成排序:将大数组拆解成小数组,小数组单独排序后,再合并成大数组。

 

用一个长度为10的数组,解释一下归并的过程:

原始数组:[72, 34, 51, 80, 14, 92, 84, 95, 68, 22]

对半拆分,直到数组变成长度为1:

对半拆分:[72, 34, 51, 80, 14][92, 84, 95, 68, 22]

继续拆分:[72, 34][51, 80, 14][92, 84][95, 68, 22]

继续拆分:[72],[34][51],[80, 14][92],[84][95],[68, 22]

最后一次:[72],[34][51],[80],[14][92],[84][95],[68],[22]

根据刚才的分组,将拆好的数组按顺序装到大数组中:

开始归并:[34, 72][51],[14, 80][84, 92][95],[22, 68]

继续归并:[34, 72][14, 51, 80][84, 92][22, 68, 95]

继续归并:[14, 34, 51, 72, 80][22, 68, 84, 92, 95]

最后一次:[14, 22, 34, 51, 68,72, 80, 84, 92, 95]

 

将上述过程翻译成代码:

拆分的过程:

function depart(arr){
  var len = arr.length;
  //长度到1了,就好了,可以return
  if(len<2){
    return arr;
  }
  //长度没到1,就继续拆
  var middle = Math.floor(len/2);
  var left = arr.slice(0,middle);
  var right = arr.slice(middle);
  //拆成左右两组后,继续递归拆分
  depart(left);
  depart(right);
}

归并的过程:

function merge(left,right){  
  //创建一个数组,存归并后的结果
  var result = [];
  //左右数组均有值时,依次把较小的push到新数组中
  while(left.length && right.length){
    if(left[0]<=right[0]){
      result.push(left.shift());
    }else{
      result.push(right.shift());
    }
  }   
//某个数组没值了,把剩余数组的剩余值依次push到新数组中   while(left.length){     result.push(left.shift());   }   while(right.length){     result.push(right.shift());   } }

把两个过程衔接起来,就是归并排序啦:

//后续步骤要用前一步的结果,所以记得加返回值,其他步骤和前面一样
function
depart(arr){   var len = arr.length;
  
if(len<2){
    return arr;
  }   
var middle = Math.floor(len/2);   var left = arr.slice(0,middle);   var right = arr.slice(middle);
  //把左右数组传给归并方法   return merge(depart(left),depart(right)); }
function merge(left,right){   var result = [];   while(left.length && right.length){     if(left[0]<=right[0]){       result.push(left.shift());     }else{       result.push(right.shift());     }   }   while(left.length){     result.push(left.shift());   }   while(right.length){     result.push(right.shift());   }
  return result; }

 

posted @ 2018-10-26 16:19  月亮和电池  阅读(144)  评论(0编辑  收藏  举报