我想使用一个mergeSort方法实现Merge Sort,该方法将int数组的序列分开,直到它是单个元素并使用方法merge将它们放在一起。 使用我的代码,我得到一个Stackoverflow错误。 任何人都知道为什么?
public static int[] mergeSort(int[] seq) {
return mergeSort(seq, 0, seq.length - 1);
}
private static int[] mergeSort(int[] seq, int l, int r) {
if (seq.length < 2) {
return seq;
}
int s = (l + r) / 2;
int[] a = new int[s];
int[] b = new int[seq.length - s];
for (int i : a) {
a[i] = seq[i];
}
for (int j : b) {
b[j] = seq[s + j];
}
mergeSort(a);
mergeSort(b);
return merge(a, b);
}
public static int[] merge(int[] ls, int[] rs) {
// Store the result in this array
int[] result = new int[ls.length + rs.length];
int i, l, r;
i = l = r = 0;
while (i < result.length) {
if (l < ls.length && r < rs.length) {
if (ls[l] < rs[r]) {
result[i] = ls[l];
++i;
++l;
} else {
result[i] = rs[r];
++i;
++r;
}
} else if (l >= ls.length) {
while (r < rs.length) {
result[i] = rs[r];
++i;
++r;
}
} else if (r >= rs.length) {
while (l < ls.length) {
result[i] = ls[l];
++i;
++l;
}
}
}
return result;
}
答案 0 :(得分:0)
堆栈溢出是通过递归调用方法太多次,可能是无限的。
private static int[] mergeSort(int[] seq, int l, int r)
这将始终以l = 0和r = seq.length-1调用,因此不需要重载。
这里:int s = (l + r) / 2;
如果数组有2个元素,这将返回0(l = 0,r = 1),因此数组将被分割为长度0和长度2(这里是什么导致无限递归调用)。在结果中添加一个,并且数组的拆分将正常工作。
要复制原始数组的部分,使用Arrays.copyOfRange()比编写自己的for循环更容易。而且您正在尝试使用数组a
和b
的现有元素(全部为0)进行索引。
答案 1 :(得分:0)
您的代码存在两个小问题。
首先是:
public static int[] mergeSort(int[] seq) {
return mergeSort(seq, 0, seq.length - 1);
}
您需要将其称为return mergeSort(seq, 0, seq.length);
背后的原因是,例如当你有2个元素并且你用-1来调用它时,你传递一个包含2个元素的数组,但s = 1 + 0/2 = 0并且你实际上并不是拆分它。每个后续的递归调用都使用一个空数组和一个具有相同2个元素的数组来完成,从而导致无限循环和堆栈溢出异常
第二个问题是这个问题:
for (int i : a) { and for (int i : b) {
您不能执行for循环,因为您希望迭代索引而不是数组的值。您需要将其更改为:
for (int i=0;i<a.length;i++) {
a[i] = seq[i];
}
for (int i=0;i<b.length;i++) {
b[i] = seq[s + i];
}
您的代码的最后一个问题是您没有分配生成的排序数组的值,当您执行递归调用时,它会返回已排序的子部分,但您无法获得结果。它应该成为:
a=mergeSort(a);
b=mergeSort(b);
这是最终的代码:
public static void main(String... args) {
int[] array={3,9,4,5,1} ;
array=mergeSort(array);
for(int i:array) {
System.out.print(i+",");
}
}
private static int[] mergeSort(int[] seq) {
if (seq.length < 2) {
return seq;
}
int s = seq.length / 2; //You always use that value. no need for 2 methods
int[] a = new int[s];
int[] b = new int[seq.length - s];
for (int i=0;i<a.length;i++) {
a[i] = seq[i];
}
for (int i=0;i<b.length;i++) {
b[i] = seq[s + i];
}
a=mergeSort(a);
b=mergeSort(b);
return merge(a, b);
}
public static int[] merge(int[] ls, int[] rs) {
// Store the result in this array
int[] result = new int[ls.length + rs.length];
int i, l, r;
i = l = r = 0;
while (i < result.length) {
if (l < ls.length && r < rs.length) {
if (ls[l] < rs[r]) {
result[i] = ls[l];
++i;
++l;
} else {
result[i] = rs[r];
++i;
++r;
}
} else if (l >= ls.length) {
while (r < rs.length) {
result[i] = rs[r];
++i;
++r;
}
} else if (r >= rs.length) {
while (l < ls.length) {
result[i] = ls[l];
++i;
++l;
}
}
}
return result;
}