已解决:在本评论的末尾发布。
我不断收到此错误,但我找不到任何解释原因。
Exception in thread "main" java.lang.StackOverflowError
at java.util.Random.nextDouble(Random.java:444)
at java.lang.Math.random(Math.java:716)
at assignment6quickSort.M6.qsAlgorithm(M6.java:50)
at assignment6quickSort.M6.qsAlgorithm(M6.java:60)
at assignment6quickSort.M6.qsAlgorithm(M6.java:60)
at assignment6quickSort.M6.qsAlgorithm(M6.java:60)
我一直在谷歌上搜索疯狂似乎没有人遇到过同样的问题,或者我愚蠢地寻找正确的事情(完全可能)。
无论如何,我正在创建随机数以找到通用quickSort的数据透视表编号,几个小时前它已经工作了一段时间,但现在我每次都会收到此错误。
拜托,我很沮丧......呵呵! 我做错了什么? 这怎么会导致溢出?
我的代码来了......
package assignment6quickSort;
import java.util.ArrayList;
import java.util.List;
import java.util.Comparator;
public class M6 {
static M6Comparator<Integer> comp = new M6Comparator<Integer>();
static Integer[] array = new Integer[20];
static ArrayList qsSorted = new ArrayList();
public static void main (String[] args) {
for (int i = 0; i < array.length; i++) {
array[i] = (int)(50 * Math.random());
}
for (int i: array) {
System.out.print(i + ", ");
}
quickSort(array, comp);
System.out.println("\n");
for (Object i: qsSorted) {
System.out.print(i + ", ");
}
}
static <T> void quickSort(T[] a, Comparator<? super T> comp) {
ArrayList<T> temp = new ArrayList<T>();
for (int i = 0; i < a.length; i++) {
temp.add(a[i]);
}
qsSorted = qsAlgorithm(temp, comp);
}
static <T> ArrayList<T> qsAlgorithm(ArrayList<T> a, Comparator<? super T> comp) {
ArrayList<T> L = new ArrayList<T>();
ArrayList<T> G = new ArrayList<T>();
if (a.size() <= 1)
return a;
int pivot = (int)Math.random() * a.size();
T pivotValue = a.get(pivot);
for (int i = 0; i < a.size(); i++) {
if (comp.compare(a.get(i), pivotValue) == -1 || comp.compare(a.get(i), pivotValue) == 0) {
L.add(a.get(i));
} else {
G.add(a.get(i));
}
}
L = qsAlgorithm(L, comp);
G = qsAlgorithm(G, comp);
L.addAll(G);
return L;
}
}
此外,这是我的比较器:
package assignment6quickSort;
import java.util.Comparator;
public class M6Comparator<E> implements Comparator<E> {
public int compare(E original, E other) {
return((Comparable<E>)original).compareTo(other);
}
}
### SOLUTION ###
显然是一个经典的递归溢出错误。非常感谢@pst和@Marcin的帮助! 这是qsAlgorithm()方法的修订版:
static <T> ArrayList<T> qsAlgorithm(ArrayList<T> a, Comparator<? super T> comp) {
ArrayList<T> L = new ArrayList<T>();
ArrayList<T> P = new ArrayList<T>();
ArrayList<T> G = new ArrayList<T>();
if (a.size() <= 1)
return a;
int pivot = (int)Math.random() * a.size();
T pivotValue = a.get(pivot);
for (int i = 0; i < a.size(); i++) {
int v = comp.compare(a.get(i), pivotValue);
if (v == -1) {
L.add(a.get(i));
} else if (v == 0) {
P.add(a.get(i));
} else {
G.add(a.get(i));
}
}
return concatenate(qsAlgorithm(L, comp), P, qsAlgorithm(G, comp));
}
static <T> ArrayList<T> concatenate(ArrayList<T> a, ArrayList<T> p, ArrayList<T> b) {
a.addAll(p);
a.addAll(b);
return a;
}
答案 0 :(得分:3)
它可能不是真正溢出堆栈的nextDouble函数,只是在每个递归步骤中调用它,因此很可能是达到限制的函数。真正的问题是你的递归过于深入(可能会停止递归的错误基本情况)。
看起来a.size
是您的variant。确保a
确实通过递归的每个步骤减少。
答案 1 :(得分:3)
您进入递归调用次数太多,直到堆栈溢出。问题是你到达主比较循环中的一个点,你总是将所有元素添加到临时数组'L',而没有添加到'G',所以你的递归调用:
L = qsAlgorithm(L, comp);
始终使用与param相同数量的元素:
ArrayList<T> a
所以你永远不会退出第49行的递归:
if (a.size() <= 1)
return a;
当你的临时数组有最后2个相等的元素时,解决方案是进行额外的退出。
编辑快速而肮脏的修复......这绝不是高效的代码。我为'even'值使用了另一个'E'集合,并将它们添加到最后的结果列表中。
static <T> ArrayList<T> qsAlgorithm(ArrayList<T> a, Comparator<? super T> comp) {
ArrayList<T> L = new ArrayList<T>();
ArrayList<T> E = new ArrayList<T>();
ArrayList<T> G = new ArrayList<T>();
if (a.size() <= 1)
return a;
int pivot = (int)Math.random() * a.size();
T pivotValue = a.get(pivot);
for (int i = 0; i < a.size(); i++) {
int v = comp.compare(a.get(i), pivotValue);
if (v == -1) {
L.add(a.get(i));
} else if (v == 0) {
E.add(a.get(i));
} else {
G.add(a.get(i));
}
}
L = qsAlgorithm(L, comp);
G = qsAlgorithm(G, comp);
L.addAll(E);
L.addAll(G);
return L;
}
答案 2 :(得分:2)
Random not 导致导致堆栈溢出的递归,但 the straw that broke the camel's back。
之前的2吨干草捆 1 :
at assignment6quickSort.M6.qsAlgorithm(M6.java:50)
at assignment6quickSort.M6.qsAlgorithm(M6.java:60)
at assignment6quickSort.M6.qsAlgorithm(M6.java:60)
at assignment6quickSort.M6.qsAlgorithm(M6.java:60)
..
1 构造代码中的问题是枢轴包含在递归子问题中。想象一下输入[x,x]
的情况,其中两个值在L
序列中以递归方式选择为x <= x
。 R
将永远是终端(0个元素),但L
永远不会是终端(2个元素)。
请参阅Quicksort on Wikipedia并注意伪代码concatenate(quicksort('less'), 'pivot', quicksort('greater'))
。也就是说,枢轴元素不包括在子问题中。