[路飞]排序数组-归并排序

126 阅读1分钟

归并排序

归并排序(Merge Sort)是建立在归并操作上的一种有效,稳定的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并

解析

  1. 先逐步进行拆分, 拆分到每一部分1个元素
  2. 合并 两两比较大小 按大小排列 合并成一个升序数组
  3. 逐步两两合并 按大小排列 两个升序数组
  4. 最终得到排好序的数组

图解下

归并排序演示.001.jpeg 归并排序演示2.001.jpeg

题解

  • 拆分到底,合并一次后 再次对数组合并 => 递归操作很方便
  • 有提到合并两个有序数组: 采用双指针的方法, 塞入新的数组中, 再对应到原数组中

代码

function sortArray(nums) {
  return mergeSort(nums, 0, nums.length - 1)
}

function mergeSort(nums, l, r) {
  // 拆分到一个的时候, 开始合并
  if (l >= r) return nums
  const mid = (l + r) >> 1
  // 1. 拆分到 left/right只有一个元素的时候
  // 2. 在开始合并(按照从小到大合并两个数) => 造次合并之前合后的两个(两个升序的合并)
  const left = mergeSort(nums, l, mid)
  const right = mergeSort(nums, mid + 1, r)

  // * 合并连个升序的数组的方法

  // * 双指针 指向两个升序数组 逐个比较添加 指针变动
  let tmp = []
  let j = 0,
    p = l,
    q = mid + 1

  while (p <= mid || q <= r) {
    if (q > r || (p <= mid && nums[p] < nums[q])) {
      tmp[j++] = nums[p++]
    } else {
      tmp[j++] = nums[q++]
    }
  }

  for (let k = 0; k < tmp.length; k++) {
    nums[l + k] = tmp[k]
  }

  tmp = null

  return nums
}

总结

  • 合并升序数组的方法
  • 双指针的使用
  • 递归理解