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,从那以后我们将合并该子数组。
图片来源:GeekForGeeks
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])); |