Merge Sort java implementation error
好的,所以我试图在Java中实现合并排序,但是在数组拆分时遇到了以下错误:
1 2 3 4 5 6 7 8
| Exception in thread "main" java. lang. IllegalArgumentException: 2 > 1
at java. util. Arrays. copyOfRange(Arrays. java:3591)
at MergeSortS. recMergeSort(MergeSortS. java:26)
at MergeSortS. recMergeSort(MergeSortS. java:28)
at MergeSortS. mergeSort(MergeSortS. java:17)
at MergeSortM. main(MergeSortM. java:16)
Java Result : 1
BUILD SUCCESSFUL (total time : 1 second ) |
我的代码段如下,请帮助我在此处确定我的问题... :(
我特意在最后注释掉了recMergeSort(right)递归调用,因为我想更正recMergeSort(left)调用...
1 2 3 4 5 6 7 8 9 10 11 12
| public void recMergeSort (int[] tempArray ){
if(tempArray. length>1){
int mid =(tempArray. length)/2;
int[] left =Arrays. copyOfRange(tempArray, 0,mid );
int[] right =Arrays. copyOfRange(tempArray,mid +1,tempArray. length-1);
recMergeSort (left );
//recMergeSort(array, right, mid+1, right.length-1);
}
} |
编辑
好的,所以我检查了另一个站点和copyOfRange方法上的javadoc,要求满足以下条件:
1 2 3 4
| Parameters:
original - the array from which a range is to be copied
from - the initial index of the range to be copied, **inclusive**
to - the final index of the range to be copied, **exclusive**. (This index may lie outside the array.) |
修复后,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12
| public void recMergeSort (int[] tempArray ){
if(tempArray. length>1){
int mid =(tempArray. length)/2;
int[] left =Arrays. copyOfRange(tempArray, 0,mid +1);
int[] right =Arrays. copyOfRange(tempArray,mid +1,tempArray. length);
recMergeSort (left );
//recMergeSort(array, right, mid+1, right.length-1);
}
} |
我收到以下错误:
请帮助我纠正此问题... :(
-
无需复制阵列。 只需使用新的lo / mid / high索引传递数组即可。
出现java.lang.StackOverflowError的原因是,您的左数组将永远不会成为大小为1的数组。如果进入if块,则意味着中位数最小值为1,因为tempArray可以满足2。然后,当您向左复制2到0时,您再次向左复制所有元素,而右边为空
看来您被Arrays.copyOfRange()方法所困扰。请尝试以下代码:
1 2 3 4 5 6 7 8 9 10
| public void recMergeSort (int[] tempArray ){
if (tempArray. length > 1 ){
int mid =(tempArray. length)/2; // mid = 2
int[] left = Arrays. copyOfRange(tempArray, 0, mid ); // [10, 20]
int[] right = Arrays. copyOfRange(tempArray, mid, tempArray. length); // [30, 40, 50]
recMergeSort (left );
//recMergeSort(array, right, mid+1, right.length-1);
}
} |
Arrays.copyOfRange(array, lowIndex, highIndex)将复制从lowIndex包含和highIndex包含的访问。这意味着左副本的highIndex应该与右副本的lowIndex相同。
用法:
1 2
| int[] tempArray = new int[] {10, 20, 30, 40, 50};
recMergeSory(tempArray); |
我认为递归太多。来自Java文档。
Thrown when a stack overflow occurs because an application recurses
too deeply.
顺便说一句:查看tempArray.length等于2时会发生什么。
我认为您的代码有错误。
1 2 3 4 5
| int mid =(tempArray. length)/2; //mid equals 1
//calls with params tempArray, 0, 2
int[] left =Arrays. copyOfRange(tempArray, 0,mid +1);
//calls with params tempArray, 2, 2
int[] right =Arrays. copyOfRange(tempArray,mid +1,tempArray. length); |
最后一行是问题。长度为2,第二个参数为2,第三个参数为2。返回数组的长度为0。
-
Arrays.copyOfRange()中的高位索引是互斥的。因此,如果您有一个包含2个元素的数组,则实际上您想传入2,它将访问array [1]。
-
我认为两个索引参数均为2。那不是问题吗?也许是我错过了一些东西。我假设第一个索引参数是包含的,并且由于它是2,所以超出范围。
-
您缺少某些东西^ ^。您要使用(tempArray, 0, mid)而不是(tempArray, 0, mid+1)。
-
那就是OPs代码。我没有发布解决方案。我发布了错误。
-
好问题。我真的不知道。我只是注意到那个可能的错误。
-
我更新了答案。考虑到您需要了解递归的深度,以避免出现异常。
在考虑了您指出的所有错误之后,我通过更改以下内容以及在OP上进行编辑来使其正常工作:
1
| int mid=(tempArray.length-1)/2; |
谢谢大家的支持。我浪费了整整一天的时间试图弄清楚这个烂摊子!
-
这不是不幸的路要走。您将枢轴(数组的中心)缩小了一个,然后使用mid + 1进行了补偿。
-
我认为蒂姆是对的。实际上,您说它正在运行,我感到很惊讶。您能提供给我们测试用例吗?
-
我只是说编译时间错误...我还没有实现排序算法
-
实施算法,然后打开一个新问题。
-
哦好的。好吧,尽管考虑蒂姆斯的评论。我认为有一些工作要做。
-
当然,我会...。拆分应该是合并排序中比较容易的部分。如果这对我来说很难,我想排序算法将需要一个新问题...:P
-
如果有人可以为我提供有关递归的优秀阅读材料,该材料具有不同递归的控制流和堆栈图,那么将不胜感激。
堆栈溢出是一个与以下事实有关的问题:对于recMergeSort的每次调用,您都在创建两个新数组。这称为log(n)次,并使堆栈变满。
要解决此问题,您可以增加堆栈大小(请参阅:java调用堆栈的最大深度是多少?),也可以通过将recMergeSort(int[] tempArray)的参数更改为recMergeSort(int[] unSortedArray, int startIndex, int endIndex)来重构代码以进行就地排序。
为了清楚起见:首先调用它是recMergeSort(array, 0, array.length-1),然后调用recMergeSort(array, startIndex, endIndex/2)和recMergeSort(array, (endIndex/2)+1, endIndex)
-
您可以用一个实际的例子证明您的观点来支持您的答案吗?如果你是对的,我会大获成功。
-
由于大小限制,实际示例很难。
-
不过,这是一个数学示例:Java的默认堆栈大小为512kb。忽略堆栈帧的开销和数组对象的开销(例如final的长度),即16384 32位int。以上面的代码示例为例,该示例创建两个新的数组,将传入的数组拆分为两个,并对其中一个执行相同的操作;在256 int处,到达递归的底部时,数组中总共将有32896 int。