我已经实现了mergesort合并功能,但是虽然我尽可能地复制了它,但是当左,中,右参数为0,0,1时,我遇到了问题。在这种情况下,逻辑似乎完全毁了。当输入数组14,7时,它输出14,7。原因是左= =中,所以它会立即插入。
这里的mergesort函数传递了测试用例,但它只调试了合并函数。
我原以为0,0,1是一个无效的参数规范,但是没有,没有其他方法可以在length = 2数组中传递中间元素。
我尝试将代码基于https://www.cs.cmu.edu/~adamchik/15-121/lectures/Sorting%20Algorithms/code/MergeSort.java
// Takes in an array that has two sorted subarrays,
// from [p..q] and [q+1..r], and merges the array
var merge = function(array, p, q, r) {
console.log(array);
console.log(p);
console.log(q);
console.log(r);
var tmp = {};
var k = p;
var middle = q;
while(p<=middle && q <= r){
console.log("aaa");
console.log(array[p]);
console.log(array[q]);
console.log("bbb");
if (array[p] < array[q]){
tmp[k] = array[p];
k++;
p++;
} else {
tmp[k] = array[q];
k++;
q++;
}
}
while(p<middle){
//tmp[k] = array[p];
k++;
p++;
}
while(r >= q){
//tmp[k] = array[q];
k++;
q++;
}
for(var i in tmp){
array[i] = tmp[i];
}
console.log(array);
console.log(tmp);
console.log("test");
};
// Takes in an array and recursively merge sorts it
var mergeSort = function(array, p, r) {
var lowerIndex = p;
var higherIndex = r;
if (lowerIndex < higherIndex) {
var middle = Math.floor(lowerIndex + (higherIndex - lowerIndex) / 2);
// Below step sorts the left side of the array
mergeSort(array,lowerIndex, middle);
// Below step sorts the right side of the array
mergeSort(array,middle + 1, higherIndex);
// Now merge both sides
merge(array,lowerIndex, middle, higherIndex);
}
};
var array = [14, 7, 3, 12, 9, 11, 6, 2];
array = [14, 7];
mergeSort(array, 0, array.length-1);
console.log("Array after sorting: " + array);
//Program.assertEqual(array, [2, 3, 6, 7, 9, 11, 12, 14]);
答案 0 :(得分:2)
中间索引必须只属于其中一个范围。目前,您正在使用<=
进行比较,因此它属于两者。
在我看来,使用表达范围的更常见约定作为第一个索引是值和第一个无效的索引会更容易混淆。您输入的0,0,1
表示第一个索引的范围超过 [0,0] ,而第二个索引的范围超过 [0,1] 。因此,在某些时候,您将array[0]
处的数据与自身进行比较,然后将其添加到输出列表中。使中间点和终点独占意味着范围 [0,1)和 [1,2)的输入是明确的。 (在一个范围内,圆括号表示独占)
答案 1 :(得分:2)
在您的命名法中,数组边界是包含的:下限是范围的第一个元素,上限是范围的最后一个元素。 mid
元素是左子数组的最后一个元素,因此,正确的数组以mid + 1
开头,您可以在调用中看到:
mergeSort(array, lowerIndex, middle); // sort left array
mergeSort(array, middle + 1, higherIndex); // sot right array
但是在merge
中,您将mid
分配到正确的范围:索引q
应该从中间的一个元素开始。 (另外,你不一致地使用限制:在第一个循环中,从p
或q
中选择smalles元素,你测试p<=middle
,这与你的命名法一致,后来你使用p<middle
。
这是您更正的merge
功能:
var merge = function(array, p, middle, r) {
console.log(p, q, r);
var tmp = {};
var k = p;
var q = middle + 1;
while(p <= middle && q <= r){
if (array[p] < array[q]){
tmp[k++] = array[p++];
} else {
tmp[k++] = array[q++];
}
}
while(p <= middle) tmp[k++] = array[p++];
while(q <= r) tmp[k++] = array[q++];
for(var i in tmp) array[i] = tmp[i];
}
我是第二个Pete建议使用独占上限。在这个术语中,子阵列为array[lo:mid]
和array[mid:hi]
,因为mid
和hi
的初始值为array.length
,不属于范围。< / p>