原作者:正月点灯笼

1.基本原理:如何将这两个数组排序并合并到下面数组中
image.png


1.合并

arr数组如何排序, 左右分成两个数组image.png
1.首先将整个数组拆成两个数组,i, j分别指向各自头部
k指向arr头部
image.png
image.png
选择i,j较小的那一个填进arr中,直到有一方数组越界
image.png

  1. const merge = (arr, l, r, m) => {
  2. // 1.split into left and right array
  3. const left = arr.slice(l, m +1),
  4. right = arr.slice(m + 1, r + 1)
  5. //2. merge into the original array i,j, k
  6. let i = 0, j = 0, k = l
  7. while (i < left.length && j < right.length) {
  8. if (left[i] < right[j]) {
  9. arr[k++] = left[i++]
  10. } else {
  11. arr[k++] = right[j++]
  12. }
  13. }
  14. while (i < left.length) {
  15. arr[k++] = left[i++]
  16. }
  17. while (j < right.left) {
  18. arr[k++] = right[j++]
  19. }
  20. }

2.分治

如果数组左右都是乱序
左右分别排序然后合并
分治法思想,不断细分直到长度为1说明必是有序的。然后合并
image.png

  1. const mergeSort = (arr, l, r) => {
  2. if (l === r){
  3. return
  4. }
  5. const m = l + Math.floor((r - l)/2)
  6. // log(m)
  7. mergeSort(arr, l, m)
  8. mergeSort(arr, m+1, r)
  9. //保证两个函数用的m是一致的(mergeSort和merge)
  10. merge(arr, l, r, m)
  11. }

总结
1.拆分
2.合并(归并)
拆成全为1的,合并,再

  1. const merge = (arr, l, r, m) => {
  2. // 1.split into left and right array
  3. const left = arr.slice(l, m +1),
  4. right = arr.slice(m + 1, r + 1)
  5. //2. merge into the original array i,j, k
  6. let i = 0, j = 0, k = l
  7. while (i < left.length && j < right.length) {
  8. if (left[i] < right[j]) {
  9. arr[k++] = left[i++]
  10. } else {
  11. arr[k++] = right[j++]
  12. }
  13. }
  14. while (i < left.length) {
  15. arr[k++] = left[i++]
  16. }
  17. while (j < right.left) {
  18. arr[k++] = right[j++]
  19. }
  20. }
  21. const mergeSort = (arr, l, r) => {
  22. if (l === r){
  23. return
  24. }
  25. const m = l + Math.floor((r - l)/2)
  26. // log(m)
  27. mergeSort(arr, l, m)
  28. mergeSort(arr, m+1, r)
  29. //保证两个函数用的m是一致的(mergeSort和merge)
  30. merge(arr, l, r, m)
  31. }
  32. // 测试
  33. const main = () => {
  34. const arr = [2, 3, 9, 7, 4, 5, 101, 11, 12]
  35. const l = 0, r = arr.length -1
  36. // merge(arr, l, r, m)
  37. mergeSort(arr, l, r)
  38. log(arr, m)
  39. }
  40. main()

回传值版


const mergeSort = (arr, l, r) => {
    if (l === r) return [arr[l]]
    const m = l + ((r - l) >> 1)
    const left = mergeSort(arr, l, m)
    const right = mergeSort(arr, m + 1, r)
    return merge(left, right)
}

const merge = (left, right) => {
    const res = []
    let p1 = p2 = 0
    let n1 = left.length, n2 = right.length
    while (p1 < n1 && p2 < n2) {
        if (left[p1] >= right[p2]) {
            res.push(left[p1++])
        } else {
            res.push(right[p2++])
        }
    }
    while (p1 < n1) {
        res.push(left[p1++])
    }
    while (p2 < n2) {
        res.push(right[p2++])
    }
    return res
}