JavaScript排序算法(二)——歸併排序

基本思想

一個分治的策略,先進行劃分,而後再進行合併
空間複雜度:nLognjavascript

自頂向下的歸併排序

採用遞歸的方式,方法比較簡潔java

function mergeSort(arr){
  // 設置終止的條件,
  if (arr.length < 2) {
    return arr;
  }
  //設立中間值
  var middle = parseInt(arr.length / 2);
  //第1個和middle個之間爲左子列
  var left = arr.slice(0, middle);
  //第middle+1到最後爲右子列
  var right = arr.slice(middle);
  if(left=="undefined"&&right=="undefined"){
     return false;
  }
  return merge(mergeSort(left), mergeSort(right));
}

function merge(left, right){
  var result = [];

  while (left.length && right.length) {
    if(left[0] <= right[0]){
      //把left的左子樹推出一個,而後push進result數組裏
       result.push(left.shift());
    }else{
      //把right的右子樹推出一個,而後push進result數組裏
     result.push(right.shift());
    }
  }
  //通過上面一次循環,只能左子列或右子列一個不爲空,或者都爲空
  while (left.length){
    result.push(left.shift());
  } 
  while (right.length){
    result.push(right.shift());
  }
  return result;
}
// 測試數據
var nums=[6,10,1,9,4,8,2,7,3,5];
mergeSort(nums);

自底向上的歸併排序

遞歸的深度太深,使用一種非遞歸的方式。首先將數據集分解爲一組只有一個元素的數組,而後經過建立一組左右子數組慢慢將它們合併起來,
每次合併都保存一部分排好序的數據,最後這個數組排序徹底。數組

function mergeSort(arr){
  if(arr.length<2){
    return;
  }
  //設置子序列的大小
  var step=1; 
  var left,right;
  while(step<arr.length){
    left=0;
    right=step;
    while(right+step<=arr.length){
      mergeArrays(arr,left,left+step,right,right+step);
      left=right+step;
      right=left+step;
    }
    if(right<arr.length){
      mergeArrays(arr,left,left+step,right,arr.length);
    }
    step*=2;
  }
}
//對左右序列進行排序
function mergeArrays(arr,startLeft,stopLeft,startRight,stopRight){
  // 創建一個左、右數組
  var rightArr=new Array(stopRight-startRight+1);
  var leftArr=new Array(stopLeft-startLeft+1);
  // 給右數組賦值
  k=startRight;
  for(var i=0;i<(rightArr.length-1);++i){
    rightArr[i]=arr[k];
    ++k;
  }
   // 給左數組賦值
  k=startLeft;
  for(var i=0;i<(leftArr.length-1);++i){
    leftArr[i]=arr[k];
    ++k;
  }
  //設置哨兵值,當左子列或右子列讀取到最後一位時,即Infinity,能夠讓另外一個剩下的列中的值直接插入到數組中
  rightArr[rightArr.length-1]=Infinity;
  leftArr[leftArr.length-1]=Infinity;
  var m=0;
  var n=0;
  // 比較左子列和右子列第一個值的大小,小的先填入數組,接着再進行比較
  for(var k=startLeft;k<stopRight;++k){
    if(leftArr[m]<=rightArr[n]){
      arr[k]=leftArr[m];
      m++; 
    }
    else{
      arr[k]=rightArr[n];
      n++;
    }
  }
}
// 測試數據
var nums=[6,10,1,9,4,8,2,7,3,5];
mergeSort(nums);

參考資料

  1. Sorting Algorithms in Javascript測試

  2. 《Data Structures& Algorithms with JavaScript》Michael McMilan著code

相關文章
相關標籤/搜索