归并排序

94 阅读1分钟

作用

思想

  • 分治,将整个数组不断地通过递归划分为两部分,直到长度为 2,再不断地进行合并,最终得到有序数组

代码

/**
 *
 * @param {Array} arr
 * @param {Number} l
 * @param {Number} r
 */
function mergeSort(arr, l, r) {
  // 只有 1 个元素退出
  if (l >= r) return
  const mid = (l + r) >> 1
  
  // 分割左区间
  mergeSort(arr, l, mid)
  
  // 分割右区间
  mergeSort(arr, mid + 1, r)

  const temp = [] // 本轮合并的结果
  let k = 0, // temp 数组当前要放值的索引
    p1 = l, // 左区间的索引
    p2 = mid + 1 // 右区间的索引

  while (p1 <= mid || p2 <= r) {
    // 如果右区间为空或左区间存在且左区间当前索引指向的值小于等于右区间
    if (p2 > r || (p1 <= mid && arr[p1] <= arr[p2])) {
      // 合并左区间的 p1 索引值到 temp 的 k 索引上,并递增两个索引
      temp[k++] = arr[p1++]
    } else {
      // 对应右区间的情况
      temp[k++] = arr[p2++]
    }
  }

  // 把当前合并结果复制到原数组
  for (let i = l; i <= r; i++) {
    arr[i] = temp[i - l]
  }
}

小分析

  • 是否稳定,因为我们合并的时候,保证了 arr[p1] <= arr[p2] 合并 p1 索引元素,所以是稳定的
  • 是否原地,不是,因为有 temp 需要额外空间