JavaScript递归选择排序递归退出问题:栈溢出错误求助
解决递归选择排序的栈溢出问题
看起来你卡在递归终止条件上啦!这个栈溢出错误(Uncaught RangeError: Maximum call stack size exceeded)几乎都是因为递归没有正确的退出逻辑,导致函数无限调用自己,把调用栈撑爆了。
先帮你补全没写完的findSmallestIndex函数,这部分逻辑是对的,只是缺了返回值:
const findSmallestIndex = (arr) => { let smallest = arr[0]; let smallestIndex = 0; const arrLen = arr.length; for (let i = 0; i < arrLen; i++) { if (arr[i] < smallest) { smallest = arr[i]; smallestIndex = i; } } return smallestIndex; // 这里要返回找到的最小元素索引 };
接下来是递归选择排序的核心问题:必须给递归加终止条件。当数组长度小于等于1时,它本身已经是有序的,直接返回就行,不需要再递归。然后每次递归处理的是「去掉当前最小元素后的剩余数组」,这样数组长度会逐渐缩小,最终触发终止条件。
给你两种实现方式,按需选择:
方式1:不修改原数组(更安全)
这种方式用slice复制数组,不会改变传入的原数组:
const selectionSort = (arr) => { // 递归终止条件:数组为空或只有一个元素时直接返回 if (arr.length <= 1) return [...arr]; const smallestIndex = findSmallestIndex(arr); const smallest = arr[smallestIndex]; // 生成去掉最小元素后的新数组 const remainingArr = [...arr.slice(0, smallestIndex), ...arr.slice(smallestIndex + 1)]; // 递归处理剩余数组,把最小元素放在最前面 return [smallest, ...selectionSort(remainingArr)]; };
方式2:使用splice修改数组(更高效,但会改变原数组)
如果不在意原数组被修改,可以用splice直接取出最小元素,减少一次数组复制:
const selectionSort = (arr) => { if (arr.length <= 1) return [...arr]; const smallestIndex = findSmallestIndex(arr); // 取出最小元素,同时修改原数组去掉这个元素 const [smallest] = arr.splice(smallestIndex, 1); return [smallest, ...selectionSort(arr)]; };
为什么之前会栈溢出?
如果你的selectionSort函数没有判断arr.length <= 1,那么即使数组只剩最后一个元素,函数还是会继续调用自己,陷入无限递归,直到调用栈达到浏览器的上限,就会抛出那个错误。
测试一下,比如调用selectionSort([5,3,6,2,10]),就能得到升序排列的[2,3,5,6,10]啦!
内容的提问来源于stack exchange,提问作者Ann Pavlov
相关产品推荐
相关产品推荐

