采用分治的办法将各个已经排序好的序列合并到一起
    算法流程:
    1、将序列切分成左右两个部分,然后继续对左右序列切分直到不能切分
    2、对切分后的序列采用合并两个排序序列的办法两两合并

    代码

    首先我们写个合并两个有序序列的办法,这里我们实现对一个的
    [p, q]位置和[m, n] **进行合并 (q + 1 = m)

    1. function merge(nums, p, q, m, n){
    2. let left = nums.slice(p, q + 1),
    3. right = nums.slice(m, n + 1)
    4. let x = 0, y = 0, i = 0
    5. while(x < left.length && y < right.length){
    6. if(left[x] <= right[y]){
    7. nums[p + i++] = left[x++]
    8. }else{
    9. nums[p + i++] = right[y++]
    10. }
    11. }
    12. while(x < left.length) nums[p + i++] = left[x++]
    13. while(y < right.length) nums[p + i++] = right[y++]
    14. return nums
    15. }

    利用递归自定到底切分,然后自底而上进行合并

    1. function MergeSort(nums, l, r){
    2. if(l == r) return
    3. let mid = (l + r) / 2 | 0 // 切分
    4. MergeSort(nums, l, mid)
    5. MergeSort(nums, mid + 1, r)
    6. merge(nums, l, mid, mid + 1, r) // 合并
    7. return nums
    8. }

    时间复杂度(O(nlog(n)))
    空间复杂度(O(n)) (不算栈空间的话)


    当然我们可以不用递归来实现,用迭代来实现
    算法流程:
    1、以2、4、8、16…等长度来对原序列进行遍历
    2、对每个范围内的元素,前半部分和后半部分进行两两归并

    代码
    **

    1. function MergeSort(nums){
    2. let len = nums.length
    3. for (let size = 1; size < len; size *= 2) {
    4. for (let low = 0; low < len - size; low += 2 * size) {
    5. merge(nums, low, low + size - 1, low + size, Math.min(low + 2 * size - 1, len - 1))
    6. }
    7. }
    8. return nums
    9. }

    合并逻辑:
    如长度为10的数组
    第一次对(0、1),(2、3),(4,、5),(6、7),(8、9)进行合并
    第二次对(0、1、2、3),(4,、5、6、7),(8、9)进行合并
    第三次对(0、1、2、3、4,、5、6、7),(8、9)进行合并
    第四次对(0、1、2、3、4,、5、6、7、8、9)进行合并