js算法:Merge Sort 归并排序

本文详细介绍了归并排序的实现原理及过程,通过示例数组[2,5,3,8,9,6,3,4,2]展示了归并排序的具体步骤,并提供了完整的JavaScript代码实现。实测该算法的时间复杂度为nlogn。

Merge Sort : 归并排序,把一个大问题分解成若干相同的小问题,解决小问题后,合并小问题结果,最终把大问题解决. 例如要排序数组 originArr = [2, 5, 3, 8, 9, 6, 3, 4, 2] 先把问题分解为排序 leftArr = [2, 5, 3, 8, 9] 和 rightArr = [6, 3, 4, 2]两个小数组,然后合并leftArr和rightArr,当排序leftArr的时候发现问题还是太复杂, 再把leftArr分解为 leftArr1 = [2, 5, 3] 和 rightArr1 = [8, 9] ...以此递归调用,直到 leftArrN = [2]...

//分治法排序
var originArr = [2, 5, 3, 8, 9, 6, 3, 4, 2]
let startTime = new Date().valueOf();
console.info("原始数组:", originArr)
function mergeSort(arr, from, to) {
  //寻找合适的分割点
  let mid = parseInt((to + from) / 2);
  if (to > from) {    //如果 to!= from 说明问题还是太复杂,递归调用分解问题
    mergeSort(arr, from, mid);
    mergeSort(arr, (mid+1), to);
    //合并左边已经排好序的,和右边已经排好序的
    merge(arr, from, mid, to);
  }
}

function merge(arr, from, mid, to) {
  let leftArr = [];
  let rightArr = [];
  //先把arr左边排好序的部分扔到临时数组leftArr中
  for(let i=from; i<= mid; i++) {
    leftArr.push(arr[i]);
  }
  //先把arr右边排好序的部分扔到临时数组rightArr中
  for(let j=mid+1; j<= to; j++) {
    rightArr.push(arr[j]);
  }
  //合并规则是,每次比较左边和右边最上面的值,把比较小的扔到arr[n]中,当左边没有了或者右边没有了,则把对应的另外一个数组剩下的值依次放入到arr[n]中
  let i=0, j=0;
  for(let n=from; n<= to; n++) {
    //左边数组没有值了,把右边数组剩下的值依次扔到arr[n]中
    if (i>= leftArr.length) {
      arr[n] = rightArr[j];
      j++;
      continue;
    }
    //右边数组没有值了,把左边数组剩下的值依次扔到arr[n]中
    if (j >= rightArr.length) {
      arr[n] = leftArr[i];
      i++;
      continue;
    }
    //如果左边右边数组都有值,把两者比较小的那个扔到arr[n]中
    if (leftArr[i] > rightArr[j]) {
      arr[n] = rightArr[j];
      j++;
    } else {
      arr[n] = leftArr[i];
      i++;
    }
  }
  // console.info(`分隔点:${from}, ${mid}, ${to}, 合并完成后:`, arr)
}

mergeSort(originArr, 0, originArr.length-1);
console.info("最终排序结果:", originArr)
let endDate = new Date().valueOf()
console.info("花费时间:", endDate - startTime)

打印结果:

原始数组: [ 2, 5, 3, 8, 9, 6, 3, 4, 2 ]
最终排序结果: [ 2, 2, 3, 3, 4, 5, 6, 8, 9 ]
花费时间: 36

归并排序的时间复杂度为nlogn

转载于:https://my.oschina.net/wanglihui/blog/692221

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值