我正在尝试实现合并排序,以便更好地了解它的工作原理。在下面的代码中,我试图对一组数字进行排序。我目前拥有的代码是错误的,并且在无限循环中运行。我现在试图非递归地解决这个问题:
function mergeSort(arr) {
var mid = Math.floor(arr.length/2);
var left = arr.slice(0, mid);
var right = arr.slice(mid, arr.length);
if (arr.length === 1) {return arr};
var sorted = [];
var i = 0;
while (left.length || right.length) {
if (left.length && right.length) {
if (left[0] < right[0]) {
sorted.push(left.shift())
} else {
sorted.push(right.shift())
}
} else if (left) {
sorted.push(left.shift())
} else {
sorted.push(right.shift())
}
i++;
}
return sorted;
}
因此,如果我有一个数组var nums = [1, 4, 10, 2, 9, 3];
,则mergeSort(nums)
应该返回[1, 2, 3, 4, 9, 10]
。
答案 0 :(得分:1)
您编写的代码将数组分成两部分并合并了一半。这不会导致排序数组,因为两个半部分没有排序。 Mergesort通过对两半进行排序,然后合并它们来工作。
有许多方法可以迭代地实现mergesort。我来提供一个。首先合并大小为1的子数组。您知道大小为1的数组已经排序,因此合并两个大小为1的连续子数组是安全的。如果对大小为1的所有连续子数组执行此操作在原始数组中,最终得到一个由大小为2的连续排序子数组组成的数组。
你知道这是怎么回事吗?现在,您可以合并每两个大小为2的连续子数组。最终得到一个大小为4的连续排序子数组的数组。继续重复此过程,直到整个数组已排序。
以下代码段实现了这种方法。
function mergeSort(arr) {
var sorted = arr.slice(),
n = sorted.length,
buffer = new Array(n);
for (var size = 1; size < n; size *= 2) {
for (var leftStart = 0; leftStart < n; leftStart += 2*size) {
var left = leftStart,
right = Math.min(left + size, n),
leftLimit = right,
rightLimit = Math.min(right + size, n),
i = left;
while (left < leftLimit && right < rightLimit) {
if (sorted[left] <= sorted[right]) {
buffer[i++] = sorted[left++];
} else {
buffer[i++] = sorted[right++];
}
}
while (left < leftLimit) {
buffer[i++] = sorted[left++];
}
while (right < rightLimit) {
buffer[i++] = sorted[right++];
}
}
var temp = sorted,
sorted = buffer,
buffer = temp;
}
return sorted;
}
function print(s) {
document.write(s + '<br />');
}
var data = [1, 4, 10, 2, 9, 3];
print('input: ' + data.join(', '));
print('output: ' + mergeSort(data).join(', '));
&#13;