我试图对这个数组进行排序:
[5 1 3 2 2 9 1]
我已经运行了调试器并且得到了奇怪的结果。我在线上设置了一个断点
merge(left, right);
在第一次传递后,这些是子数组:
left = [1 3 5 2 2]
right = [9]
所以我非常确定'划分'部分是我出错的地方。有人可以查看我的代码,看看他们是否能发现错误?
public int[] arrayToSort = { 5, 1, 3, 2, 2, 9, 1 };
...
private void mergeSort(int[] array, int low, int high) {
// Base case
if (!(high - low <= 1)) {
int mid = low + (high - low) / 2;
// Split array into sub-arrays
int[] left = new int[mid];
int[] right = new int[high - mid];
// Fill sub-arrays
for (int i = low; i < mid; i++) {
left[i - low] = array[i];
}
for (int i = mid; i < high; i++) {
right[i - mid] = array[i];
}
mergeSort(left, low, mid);
mergeSort(right, mid + 1, high);
merge(left, right);
} else {
return;
}
}
private void merge(int[] left, int[] right) {
int lLength = left.length;
int rLength = right.length;
// Pointer for left array
int i = 0;
// Pointer for right array
int j = 0;
// Pointer for merged array
int k = 0;
while (i < lLength && j < rLength) {
if (left[i] < right[j]) {
arrayToSort[k] = left[i];
i++;
} else {
arrayToSort[k] = right[j];
j++;
}
k++;
}
while (i < lLength) {
arrayToSort[k] = left[i];
i++;
k++;
}
while (j < rLength) {
arrayToSort[k] = right[j];
j++;
k++;
}
}
感谢任何帮助!
编辑:注意到我的代码中的错误(参数未被使用)并对其进行了修改。这是我现在得到的错误(来自上面的代码):
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4
at Launcher.mergeSort(Launcher.java:43)
at Launcher.mergeSort(Launcher.java:49)
at Launcher.main(Launcher.java:21)
所以它在线上抱怨
left[i - low] = array[i];
答案 0 :(得分:0)
你能发现这个片段中的问题吗? - &GT;
int mid = low + (high - low) / 2;
int[] left = new int[mid];
int[] right = new int[high - mid];
// ...
mergeSort(left, low, mid);
mergeSort(right, mid + 1, high);
left
和right
的大小以及传递给mergeSort
的递归调用的索引怎么样?
您传递的索引是接收数组中的索引,而不是left
和right
中的索引。
当你看right
时,问题最为明显。索引high
将不可避免地总是超出范围。
以上会更有意义:
mergeSort(left, 0, left.length);
mergeSort(right, 0, high.length);
现在索引是正确的。它们也毫无意义,因为现在它们只是子阵列的全部范围,因此根本不需要。这种古怪只是一个更深层次问题的症状。
请记住merge
最终必须更新原始数组。为此,它需要对原始数组的引用,以及左右范围。您正在传递合并左右子数组。在您的实现中将丢失对原始数组的引用和范围的索引。
考虑一下:
int mid = low + (high - low) / 2;
mergeSort(array, low, mid);
mergeSort(array, mid + 1, high);
merge(array, low, mid, high);
请注意:
相应地更改merge
的实现,以合并数组中指定的范围,修改该数组。一种简单的方法是将范围合并为大小为高 - 低的工作数组,然后从合并的工作数组复制回原始范围。
答案 1 :(得分:0)
只看代码,第二个递归调用应该是:
return new Blob([ia.buffer], {type:mimeString});
为左侧分配了比所需更多的空间:
mergeSort(right, mid, high);
Merge()函数需要一个低参数来知道在哪里开始合并(k =低,而不是k = 0)。
我想知道为什么自下而上合并排序很少被教授,因为它更容易理解。