前端排序算法之归并排序

165 阅读2分钟

归并排序借鉴了分治的思想,把大的排序数组先分(logN层),后治(合并)

对于分和治来说,可以把这两个部分单独去理解

分就是把数组尽可能的分小,8分为4,4分为2

function sort (array, left, right) {
    if (left < right) {
        const mid = left + ((right - left) >> 1)
        sort(array, left, mid)
        sort(array, mid + 1, right)
    }
}
  • 在左右两个索引没有重合时,一直分下去
  • 四则运算没有按位计算更快
  • left + (right - left) / 2 能避免加法的溢出

分的功能就完成了

所谓治,就是把分到底的数组进行一个排序,因为我们最终的目的也是要排序嘛

function merge (array, left, mid, right) {
    const temp = []
    let i = 0
    let l = left
    let m = mid + 1
    // 判断哪边比较大
    while(l <= mid && m <= right) {
      temp.push(array[l] >= array[m] ? array[m++] : array[l++])
    }
    // 如果左边还有剩的也加入
    while(l <= mid) {
      temp.push(array[l++])
    }
    // 如果右边还有剩的也加入
    while(m <= right) {
      temp.push(array[m++])
    }
    // 把得到的排序好的数组替换原数组
    while(i < temp.length) {
      array[left + i] = temp[i++]
    }
}

其实排序的思路在于两个指针,对left到mid,mid+1到right两个数组之中的元素比较放入一个临时数组中

举个例子:

// [1, 3, 2, 4]
// 初始指针
let l = left = 0, m = mid = 2
// 看arr[l]大还是arr[m]大,谁大谁后放,先放的把指针向后挪一位
while(l <= mid && m <= right) {
    temp.push(array[l] >= array[m] ? array[m++] : array[l++])
}
// 如果另一边的指针到最后了,但是这边还加完,那就继续加到temp里
while(l <= mid) {
    temp.push(array[l++])
}
// 最后替换

顺序就是:

  1. 1和2比较,1先入
  2. 3和2比较,2先入
  3. 3和4比较,3先入
  4. 4插入

合并

把分和治的部分完成好,那就需要合并在一块

function mergeSort (array) {
  function sort (array, left, right) {
    if (left < right) {
        const mid = left + ((right - left) >> 1)
        sort(array, left, mid)
        sort(array, mid + 1, right)
        merge(array, left, mid, right)
    }
  }
  function merge (array, left, mid, right) {
    const temp = []
    let i = 0
    let l = left
    let m = mid + 1
    while(l <= mid && m <= right) {
        temp.push(array[l] >= array[m] ? array[m++] : array[l++])
    }
    while(l <= mid) {
        temp.push(array[l++])
    }
    while(m <= right) {
        temp.push(array[m++])
    }
    while(i < temp.length) {
        array[left + i] = temp[i++]
    }
  }
  sort(array, 0, array.length - 1)
  return array
}

前端的归并算法就完成啦!

归并排序的时间复杂度为O(nlogn),因为有递归,包括了所以空间复杂度为O(n)

如果有什么问题,请在下方留言