Java 增加堆栈大小是否被认为是一种不好的做法?
我在Java程序中得到了StackOverflowException,因此我使用Java 增加堆栈大小是否被认为是一种不好的做法?,java,stack-overflow,depth-first-search,Java,Stack Overflow,Depth First Search,我在Java程序中得到了StackOverflowException,因此我使用-Xss100m增加了堆栈大小。这是否意味着我的代码有问题?我需要解决以下任务: 你有n件衣服 对于每一件衣服x,y,你知道x和y的搭配是否合适 把所有的衣服都放在最大数量的衣柜里,但你必须确保当你从每个衣柜里拿出一件衣服时,它看起来会很好(所以每件衣服都必须看起来很好) 我将其实现为一个图,其中顶点是衣服,当两个顶点彼此看起来不合适时,两个顶点之间有一条边。所以基本上我需要把每个连接顶点的“组”放在一个衣柜里。为此
-Xss100m
增加了堆栈大小。这是否意味着我的代码有问题?我需要解决以下任务:
Map<Integer, List<Integer>> edges;
/**
* Recursive implementation of DFS algorithm adjusted to SimpleGraph class
*
* @param vertice id of vertice we start at
* @param visited array holding info if given vertice was visited or not
* @param applyToEachVertice function applied to each vertice we visit
* @return did we marked ANY vertice as visited ( if we DFS starting at
* visited vertice it returns false and true otherwise )
*/
boolean deepFirstSearch( int vertice, boolean[] visited, Consumer<Integer> applyToEachVertice )
{
if(visited[vertice])
return false;
visited[vertice] = true;
applyToEachVertice.accept(vertice);
// checks if vertice has any neighbours
if(!edges.containsKey(vertice))
return true;
for( int v : edges.get(vertice) )
if(!visited[v])
deepFirstSearch(v, visited, applyToEachVertice);
return true;
}
映射边缘;
/**
*调整为SimpleGraph类的DFS算法的递归实现
*
*@param vertice我们开始的vertice id
*@param已访问阵列,如果已访问或未访问给定的vertice,则保留信息
*@param applyToEachVertice函数应用于我们访问的每个vertice
*@return我们是否将任何vertice标记为已访问(如果我们从
*已访问vertice返回false,否则返回true)
*/
布尔deepFirstSearch(int vertice、访问的布尔[]、消费者应用程序EachVertice)
{
如果(访问[垂直])
返回false;
访问[垂直]=真实;
applyToEachVertice.接受(vertice);
//检查vertice是否有邻居
如果(!edges.containsKey(垂直))
返回true;
for(int v:edges.get(vertice))
如果(!已访问[v])
deepFirstSearch(v、已访问、适用于每个社区);
返回true;
}
主回路
void resolve( SimpleGraph sg )
{
boolean[] visited = new boolean[sg.getVertNumber()];
final int[] wardrobe = new int[sg.getVertNumber()];
for(int i = 0, warNr = 0; i < sg.getVertNumber(); i++)
{
final int cNr = warNr;
if(sg.deepFirstSearch(i, visited, x -> wardrobe[x] = cNr))
warNr++;
}
}
void解析(SimpleGraph sg)
{
boolean[]已访问=新的boolean[sg.getVertNumber()];
最终整数[]衣柜=新整数[sg.getVertNumber()];
for(inti=0,warner=0;i衣柜[x]=cNr))
华纳++;
}
}
编辑:以迭代方式实际实现DFS解决了问题。这意味着我可以在不改变堆栈大小的情况下运行我的应用程序
boolean deepFirstSearchNotRecursive( int vertice, boolean[] visited, Consumer<Integer> applyToEachVertice )
{
if(visited[vertice])
return false;
Deque<Integer> stack = new ArrayDeque<>();
stack.push(vertice);
while(!stack.isEmpty())
{
Integer next = stack.pop();
visited[next] = true;
applyToEachVertice.accept(next);
if(!edges.containsKey(next))
continue;
for(Integer i : edges.get(next))
if(!visited[i])
stack.push(i);
}
return true;
}
boolean deepFirstSearchNotRecursive(int-vertice,boolean[]已访问,消费者应用程序每个权限)
{
如果(访问[垂直])
返回false;
Deque stack=new ArrayDeque();
栈.推(垂直);
而(!stack.isEmpty())
{
整数next=stack.pop();
访问[下一步]=真;
applyToEachVertice.accept(下一步);
如果(!edges.containsKey(下一个))
继续;
for(整数i:edges.get(下一个))
如果(!访问[i])
堆栈推送(i);
}
返回true;
}
我假定您的问题不是由无限递归引起的,因为您可以从StackOverflowException
stacktrace中发现问题,扩展堆栈大小对您没有帮助
虽然有充分的理由增加堆栈跟踪大小,但我敢说,调用链的深度与传递给应用程序的输入的大小成正比。在这种情况下,您永远无法将其配置得足够大(如果您不限制输入的大小,这对于图形来说可能是一件棘手的事情)。切换到递归深度独立于输入数据的算法是一种方法
当然,如果您有预定义的数据集,或者编写了一个永远不会重复使用的一次性脚本,那么捷径比重新实现算法的核心更可取。如果您知道可以这样做并且可以安全地使用它,则可以增加堆栈大小。否则,我会尝试看看一个不同的算法是否有助于从一开始就避免SO。如果让我猜的话,我会说你可能陷入了一个无限循环,所以你的内存用完了。如果增加堆栈大小可以解决问题,那么很可能不是无限循环。我错了吗?顺便说一句,将DFS实现为非递归方法现在解决了这个问题:)我从来没有出现过无法通过修复代码来修复的堆栈溢出。因此,看看我的代码,你有没有看到任何简单的方法来修复此问题(除了已经修复的方法)?