关于数组:javascript合并排序和递归

javascript merge sort and recursion

我试图了解JavaScript合并排序功能的工作方式。而且我很难理解递归函数的工作原理。这是代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const mergeSort = array => {
  if (array.length < 2) {
    //function stop here
    return array
  }

  const middle = Math.floor(array.length / 2);
  const leftSide = array.slice(0, middle);
  const rightSide = array.slice(middle, array.length);
  return merge(mergeSort(leftSide), mergeSort(rightSide))

};

const merge = (left, right) => {
  const result = [];

  while (left.length && right.length) {
    if (left[0] <= right[0]) {
      result.push(left.shift());
    } else {
      result.push(right.shift);
    }
  }

  while(left.length) result.push(left.shift());

  while(right.length) result.push(right.shift());

  return result;
}
mergeSort([5,3,8,10,4,1])

使用mergeSort函数分割初始数组后,传递给merge函数的前两个元素为3和8。随后再次调用merge,但使用另一个值,并且仍保留先前的输入。这怎么可能-调用一次后,它会保留值([3,8])并向它们添加更多值?

我从中获取代码的YouTube视频


要了解递归,您可以使用缩进来跟踪所有递归级别。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
const mergeSort = (array, level) => {
  logWithLevel(level,"Start sort array" + array);
  if(array.length < 2) {
    //function stop here
    logWithLevel(level,"Finish sort array" + array);
    return array;
  }

  const middle = Math.floor(array.length / 2);
  logWithLevel(level,"middle element is" + array[middle])
  const leftSide = array.slice(0, middle);
  const rightSide = array.slice(middle, array.length);
  var result = merge(mergeSort(leftSide, level + 1), mergeSort(rightSide, level + 1));
  logWithLevel(level,"Finish sort array" + result);
  return result;
};

const merge = (left, right) => {
  const result = [];

  while(left.length && right.length){
    if(left[0] <= right[0]){
      result.push(left.shift());
    }else{
      result.push(right.shift());
    }
  }

  while(left.length) result.push(left.shift());

  while(right.length) result.push(right.shift());

  return result;
}

const logWithLevel = (level, data) => {
    var s =""
    for (i = 0; i < level; i++) {
        s +="   ";
    }
    console.log(s + data);
}

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
> mergeSort([5,3,8,10,4,1], 0)
    Start sort array 5,3,8,10,4,1
    middle element is 10
        Start sort array 5,3,8
        middle element is 3
            Start sort array 5
            Finish sort array 5
            Start sort array 3,8
            middle element is 8
                Start sort array 3
                Finish sort array 3
                Start sort array 8
                Finish sort array 8
            Finish sort array 3,8
        Finish sort array 3,5,8
        Start sort array 10,4,1
        middle element is 4
            Start sort array 10
            Finish sort array 10
            Start sort array 4,1
            middle element is 1
                Start sort array 4
                Finish sort array 4
                Start sort array 1
                Finish sort array 1
            Finish sort array 1,4
        Finish sort array 1,4,10
    Finish sort array 1,3,4,5,8,10

根据分而治之的原则合并排序工作。在这里,问题被划分为较小的子问题,并一直持续到问题得以解决为止。然后,我们通过组合较小的已解决问题来解决较大的问题。

在合并排序中,我们将数组划分为较小的数组,直到其大小为1并且已经对大小为1的数组进行了排序。之后,我们将合并较小的数组,以便对新创建的数组也进行排序。

在该图中,您可以在第四层中看到所有子数组的大小均为1,从那以后我们将合并该子数组。

enter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function mergeSort(input) {
  const {length:arraySize} = input;
  if (arraySize < 2) return input;
  const mid = Math.floor(arraySize/2);
  const sortedLeftArray = mergeSort(input.slice(0,mid));
  const sortedRightArray = mergeSort(input.slice(mid, arraySize));
  return merge(sortedLeftArray, sortedRightArray);
}

function merge (left, right){
  let result = []
  while(left.length && right.length){
    if(left[0]< right[0]){
      result.push(left.shift())
    }else{
      result.push(right.shift())
    }
  }
  /* Either left/right array will be empty or both */
  return [...result, ...left, ...right];
}

console.log(mergeSort([5,3,8,10,4,1]))


1
Sorting with recursive

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function sort(arr){
const staticArr = [...arr]
  function recMaxSort(arrayARG,maxEL=0,resultArr = []){
    const [firstEl,...rest] = arrayARG;
    if (staticArr.length === resultArr.length){
      return resultArr
    }
    if (!firstEl){
      resultArr=[maxEL,...resultArr]
      const newArray = staticArr.filter(el=>{return !resultArr.includes(el)})
      return recMaxSort(newArray,0,resultArr)
    }

    if (maxEL>firstEl){
      return recMaxSort(rest,maxEL,resultArr)
    } else if (firstEl>=maxEL){
      return recMaxSort(rest,firstEl,resultArr)
    }

  }

  return  recMaxSort(arr)

}

 
 console.log(sort([231,4,7,3,54,500]));