我在Java中使用合并排序代码遇到两个问题。
当我输入数组[3,4,2,1,0,6,8]时,我得到输出[0,1,2,3,4,6,0] ,这显然是错误的。
我怀疑我编写代码的方式不尽如人意。如果您能找到任何改进,请告诉我。我知道网上已有大量的mergesort算法,但我要具体询问我编写代码的方式。谢谢!
import java.util.Arrays;
public class Main {
static int[] mergeSort(int[] arr) {
if (arr == null)
return null;
if (arr.length <= 1)
return arr;
int length = arr.length;
int mid = arr.length / 2;
int[] left = Arrays.copyOfRange(arr, 0, mid);
int[] right = Arrays.copyOfRange(arr, mid, length);
int[] sortedLeft = mergeSort(left);
int[] sortedRight = mergeSort(right);
int leftSmallestIndex = 0;
int rightSmallestIndex = 0;
int leftLength = left.length;
int rightLength = right.length;
int[] sortedArr = new int[length];
outer: for (int i = 0; i < length; i++) {
if (leftSmallestIndex >= leftLength) {
while (rightSmallestIndex < rightLength) {
sortedArr[i] = sortedRight[rightSmallestIndex];
rightSmallestIndex++;
break outer;
}
}
if (rightSmallestIndex >= rightLength) {
while (leftSmallestIndex < leftLength) {
sortedArr[i] = sortedLeft[leftSmallestIndex];
leftSmallestIndex++;
break outer;
}
}
if (sortedLeft[leftSmallestIndex] < sortedRight[rightSmallestIndex]) {
sortedArr[i] = sortedLeft[leftSmallestIndex];
leftSmallestIndex++;
}
else {
sortedArr[i] = sortedRight[rightSmallestIndex];
rightSmallestIndex++;
}
}
return sortedArr;
}
public static void main(String[] args) {
// write your code here
int[] a = new int[] {3,4,2,1,0,6,8};
System.out.println(Arrays.toString(mergeSort(a)));
}
}
答案 0 :(得分:3)
你的语句break outer;
实际上导致控件退出for循环,它不会继续for循环(我猜你正试图继续使用for循环,使用break outer;
声明)。
这会导致循环仅更新sortedRight
或sortedLeft
中的一个剩余元素以进入已排序的数组而其他元素被遗漏,这导致0
结束时你的循环。
你实际上不需要这样做,你可以循环直到 - leftSmallestIndex < leftLength && rightSmallestIndex < rightLength
,然后在for循环中定义你在for循环中定义的while循环。
示例 -
import java.util.*;
import java.math.*;
class a {
static int[] mergeSort(int[] arr) {
if (arr == null)
return null;
if (arr.length <= 1)
return arr;
int length = arr.length;
int mid = length / 2;
int[] left = Arrays.copyOfRange(arr, 0, mid);
int[] right = Arrays.copyOfRange(arr, mid, length);
int[] sortedLeft = mergeSort(left);
int[] sortedRight = mergeSort(right);
int leftSmallestIndex = 0;
int rightSmallestIndex = 0;
int leftLength = left.length;
int rightLength = right.length;
int[] sortedArr = new int[length];
int i = 0;
for (; leftSmallestIndex < leftLength && rightSmallestIndex < rightLength;i++) {
if (sortedLeft[leftSmallestIndex] < sortedRight[rightSmallestIndex]) {
sortedArr[i] = sortedLeft[leftSmallestIndex];
leftSmallestIndex++;
}
else {
sortedArr[i] = sortedRight[rightSmallestIndex];
rightSmallestIndex++;
}
}
while (rightSmallestIndex < rightLength) {
sortedArr[i] = sortedRight[rightSmallestIndex];
rightSmallestIndex++;
i++;
}
while (leftSmallestIndex < leftLength) {
sortedArr[i] = sortedLeft[leftSmallestIndex];
leftSmallestIndex++;
i++;
}
return sortedArr;
}
public static void main(String[] args) {
int[] a = new int[] {3,4,2,1,0,6,8};
System.out.println(Arrays.toString(mergeSort(a)));
outer : for(int i = 0;i < 10 ; i++) {
while(true) {
System.out.println(i);
break outer;
}
}
}
}
最后,我添加了示例(使用break outer;
尝试的简单版本,它应该可以帮助您了解发生了什么)。
答案 1 :(得分:2)
您的问题出在while循环中:
while (rightSmallestIndex < rightLength) {
sortedArr[i] = sortedRight[rightSmallestIndex];
rightSmallestIndex++;
break outer;
}
永远不会循环,因为你的break语句是INSIDE while。此外,你不会在while内部增加i
,所以即使它循环,它也会覆盖当前索引处的值而不是填充数组的其余部分
将它们更改为
if (leftSmallestIndex >= leftLength) {
while (rightSmallestIndex < rightLength) {
sortedArr[i] = sortedRight[rightSmallestIndex];
rightSmallestIndex++;
i++;
}
break outer;
}
if (rightSmallestIndex >= rightLength) {
while (leftSmallestIndex < leftLength) {
sortedArr[i] = sortedLeft[leftSmallestIndex];
i++;
leftSmallestIndex++;
}
break outer;
}
..rest is the same
应该给你正确的结果
至于改进......
不要使用标签和break LABEL
声明,它会让人感到非常困惑。可能更清楚的是将这些部分重构为他们自己的方法,意图揭示方法名称,如fillInRemainingArray()
我认为你不需要复制数组,你应该能够只用1个数组合并