TypeScript选择排序类连续调用双排序方法失效问题求助
我学习了简单的选择排序(selection sort)算法并尝试用JavaScript/TypeScript实现。以下是我的SelectionSort类代码:
export default class SelectionSort { private dataForSmallestToBiggest: number[]; private dataForBiggestToSmallest: number[]; public startData: number[]; private biggestIndex: number = 0; private biggest: number = 0; private smallestIndex: number = 0; private smallest: number = 0; public iterationSmallestToBiggest: number = 0; public iterationBiggestToSmallest: number = 0; constructor(data: number[]) { // initiate for array smallest to biggest this.dataForSmallestToBiggest = data; // initiate for array biggest to smallest this.dataForBiggestToSmallest = data; // initiate for start data this.startData = data; } // set biggest data private setBiggest() { // initiate biggest data this.biggest = this.dataForBiggestToSmallest[0]; //initiate biggest index data this.biggestIndex = 0; // looping for searching biggest index and biggest value from array this.dataForBiggestToSmallest.forEach((val, index) => { // if biggest found if (val > this.biggest) { // change biggest value this.biggest = val; // change biggest index this.biggestIndex = index; } // increase how many iteration for this looping this.iterationBiggestToSmallest++; }); } // searching smallest data private setSmallest() { // initiate smallest data this.smallest = this.dataForSmallestToBiggest[0]; //initiate smallest index data this.smallestIndex = 0; // looping for searching smallest index and smallest value from array this.dataForSmallestToBiggest.forEach((val, index) => { // if smallest found if (val < this.smallest) { // change the smallest value this.smallest = val; // change the smallest index this.smallestIndex = index; } // increase how many iteration for this looping this.iterationSmallestToBiggest++; }); } // sorting from smallest to biggest public smallestToBiggest() { // initiate result variable let result: number[] = []; while (this.dataForSmallestToBiggest.length > 0) { // change smallest value and smallest index this.setSmallest(); // add result from smallest data; result.push(this.smallest); // remove array by smallest inex this.dataForSmallestToBiggest.splice(this.smallestIndex, 1); // increase how many sorting smallest to biggest sort this.iterationSmallestToBiggest++; } return result; } // sorting from biggest to smallest public biggestToSmallest() { // initiate result variable let result: number[] = []; while (this.dataForBiggestToSmallest.length > 0) { // change biggest value and biggest index this.setBiggest(); // add result result.push(this.biggest); // remove array by biggest inex this.dataForBiggestToSmallest.splice(this.biggestIndex, 1); // increase how many sorting smallest to biggest sort this.iterationBiggestToSmallest++; } return result; } }
单独调用biggestToSmallest或smallestToBiggest方法时,排序功能均正常。但同时调用两个方法时,仅biggestToSmallest生效,smallestToBiggest无结果输出,且startData属性也被清空。请问我的代码哪里出错了?为何仅第一个方法有效?
问题根源
JavaScript/TypeScript中数组是引用类型,你在构造函数里直接将传入的data数组赋值给三个类属性,这意味着三个变量实际上指向内存中的同一个数组。当你调用任意一个排序方法时,方法内部通过splice()修改数组(删除元素),会直接改变这个共享的原数组。
比如先调用biggestToSmallest,方法会循环删除数组元素直到为空,此时dataForSmallestToBiggest和startData指向的也是这个空数组,后续调用smallestToBiggest时,循环条件this.dataForSmallestToBiggest.length > 0不成立,直接返回空数组。
修复方案
在构造函数中为每个属性创建独立的数组副本,避免引用共享。对于纯数字数组,使用扩展运算符[...data]或data.slice()即可实现浅拷贝:
constructor(data: number[]) { // 创建独立数组副本,避免相互影响 this.dataForSmallestToBiggest = [...data]; this.dataForBiggestToSmallest = [...data]; this.startData = [...data]; }
修改后,每个排序方法操作的都是自己专属的数组副本,调用顺序不再影响结果,startData也会始终保留初始的数组值。
内容的提问来源于stack exchange,提问作者Al Youma Akmal

