javascript - 一个简单的 selectionSort 但无休止地运行
问题描述
我写了一个简单的seletionSort:
function selectionSort(arr) {
let copyArr = [...arr];
let newArr = [];
while (copyArr) {
minimum = Math.min(...copyArr);
newArr.push(minimum);
console.log("newArr", newArr);
copyArr.splice(arr.indexOf(minimum), 1);
console.log("copyArr", copyArr);
}
return newArr;
}
不幸的是,当应用到时arr = [-7, 34, 27, 87, 21, 0, -11]
,它会无休止地运行并输出:
newArr [ -11 ]
copyArr [ -7, 34, 27, 87, 21, 0 ]
newArr [ -11, -7 ]
copyArr [ 34, 27, 87, 21, 0 ]
newArr [ -11, -7, 0 ]
copyArr [ 34, 27, 87, 21, 0 ]
...
newArr [
-11, -7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,
... 752 more items
]
有什么问题?
解决方案
你有两个主要问题:
数组总是真实的,即使它们是空的
[]
。这意味着您的 while 循环将继续执行,因为在您的条件下[]
使用时将被评估为 true 。while
您可以将条件更改为在长度为 0 时停止,这可以通过检查是否.length
为真/假来完成。您正在从数组中拼接错误的索引。目前,您正在使用数组,但这会在删除
arr.indexOf(minimum)
任何元素之前为您提供元素的索引。copyArray
这意味着元素arr
的索引 from 与索引 from 不匹配copyArray
。您可以更改它以查找copyArray.indexOf()
索引,以在 copyArray 中找到最小值的正确索引
function selectionSort(arr) {
let copyArr = [...arr];
let newArr = [];
while (copyArr.length) {
minimum = Math.min(...copyArr);
newArr.push(minimum);
console.log("newArr", newArr);
copyArr.splice(copyArr.indexOf(minimum), 1);
console.log("copyArr", copyArr);
}
return newArr;
}
console.log(selectionSort([4, 2, 10, 1]));
对于稍微优化的解决方案,请考虑创建一个函数来查找最小数字的索引,然后执行交换。这样你就不需要迭代数组两次来找到最小数字然后找到那个数字的位置
function findMinIndex(arr, start) {
let minIdx = start;
for(let i = start+1; i < arr.length; i++) {
if(arr[i] < arr[minIdx]) {
minIdx = i;
}
}
return minIdx;
}
function selectionSort([...arr]) {
for(let i = 0; i < arr.length-1; i++) {
const minIdx = findMinIndex(arr, i); // get pos of min
// Swap the two elements around
const tmp = arr[i];
arr[i] = arr[minIdx];
arr[minIdx] = tmp;
}
return arr;
}
console.log(selectionSort([4, 2, 10, 1]));