Цикл слияния должен остановиться, когда либо список пуст: вместо while (this.length > 0 || arr.length > 0)
вы должны написать:
while (this.length > 0 && arr.length > 0)
Более того, вы не должны break
из цикла после каждогосохранить в массиве merge
, и избыточно сравнивать элементы дважды.
Вот исправленная версия:
Array.prototype.merge = function(arr, callback) {
let merged = [];
while (this.length > 0 && arr.length > 0) {
if (callback(this[0], arr[0]) < 0) {
merged.push(arr.shift());
} else {
merged.push(this.shift());
}
}
merged = merged.concat(this);
return merged.concat(arr);
};
Обратите внимание, что ваш метод merge
сортирует массивв порядке убывания, и функция callback
по умолчанию сравнивает элементы также в порядке убывания, в результате чего массив сортируется в порядке возрастания по совпадению.Возможно, вы захотите упростить это и принять функцию обратного вызова null
в merge
.
Вот более общая версия:
Array.prototype.mergeSort = function(callback) {
if (this.length <= 1)
return this;
const mid = this.length >> 1;
const sortedLeft = this.slice(0, mid).mergeSort(callback);
const sortedRight = this.slice(mid).mergeSort(callback);
return sortedLeft.merge(sortedRight, callback);
};
Array.prototype.merge = function(arr, callback) {
let merged = [];
if (callback) {
while (this.length > 0 && arr.length > 0) {
if (callback(this[0], arr[0]) <= 0) {
merged.push(this.shift());
} else {
merged.push(arr.shift());
}
}
} else {
while (this.length > 0 && arr.length > 0) {
if (this[0] <= arr[0]) {
merged.push(this.shift());
} else {
merged.push(arr.shift());
}
}
}
return merged.concat(this).concat(arr);
};