我正在做一个在java中的8件益智游戏,并做了一个DFS查找解决方案的任务命令,从随机状态开始。DFS stackoverflow错误
我有一个Node类,每个Node对象知道它在使用int [] []和它的父节点是什么状态。此外,它知道什么方向,它可以移动的(左,右,上,下)
goal state: start state (random):
[0 1 2] [1 8 0]
[3 4 5] [3 7 4]
[6 7 8] [2 5 6]
开始一个节点,起始节点,我的程序会为所有可能的子节点。它检查空白方块可以移动的方向,它检查它是否不回到已经属于另一个节点的状态。因此在本例的情况下开始节点之上将展开如下:
[1 8 0]
A) [3 7 4]
[2 5 6]
/ \
[1 0 8] [1 8 4]
B) [3 7 4] [3 7 0] C)
[2 5 6] [2 5 6]
// / \
... ... [1 8 4] [1 8 4]
D) [3 0 7] [3 7 6] E)
[2 5 6] [2 5 0]
/// / \
... ... ... [1 8 4] NO
F) [3 7 6] CHILD
[2 0 5]
/ \
... ...
我处理这是我探索的第一个节点,推动它的所有孩子一个堆栈的方式,这种情况发生在一个递归的方法,循环扩展各个节点,直到达到目标状态或达到截止(编号i提供,以避免无休止的循环下去)
stack = [A]
pop()
stack = []
A -> B
push(B)
stack = [B]
A -> C
push(C)
stack = [C|B]
A -> NO MORE CHILDREN
pop()
stack = [B]
C -> D
push(D)
stack = [D|B]
C -> E
push(E)
stack = [E|D|B|]
C -> NO MORE CHILDREN
pop()
stack = [D|B|]
E -> F
push(F)
stack = [F|D|B]
E -> NO MORE CHILDREN
pup()
stack = [D|B]
代码工作很好,只要我的截止不算太高,如果它比我得到的错误:java.lang.StackOverflowError
我做错了什么?
public void expand(Node parent, int cutoff){
cutoff--;
int[][] currentState = parent.getState();
if(Arrays.deepEquals(currentState, goalState)){
found = true;
goalNode = parent;
}
if(cutoff>0 && !found){
if(parent.up){
Node child = createUPnode();
child.setParent(parent);
stack.push(child);
parent.up = false;
expand(parent, cutoff)
}
else if(parent.right){
Node child = createRIGHTnode();
child.setParent(parent);
stack.push(child);
parent.right = false;
expand(parent, cutoff)
}
else if(parent.down){
Node child = createDOWNnode();
child.setParent(parent);
stack.push(child);
parent.down = false;
expand(parent, cutoff)
}
else if(parent.left){
Node child = createLEFTnode();
child.setParent(parent);
stack.push(child);
parent.left = false;
expand(parent, cutoff)
}
else{
Node nextNode = stack.pop();
expand(nextNode, cutoff);
}
}
else{
System.out.println("CUTOFF REACHED");
}
}
谢谢你,我增加了堆栈大小,并摆脱了stackoverflow错误,但我觉得它需要很长时间才能解决这个难题,至少我在网上看到的其他8个拼图可以解决自己10秒,我的算法有什么问题吗?或者DFS采取这么长时间很自然? – Alex 2011-05-03 11:30:15
也许你在网上看到的解决方案使用了一些启发式的步骤。例如,我不认为你必须考虑通过执行向下操作来扩展当前节点到达时与Up操作对应的节点。因为你只是回到父节点,对吧?这是一个简单的技巧,它已经消除了找到解决方案所需扩展的25%(粗略的,也许是错误的估计)。我相信你可以考虑其他这样的规则来进一步改进搜索。 – phuibers 2011-05-03 11:41:49
还有第三个选项可以消除这个问题。明确堆栈并消除递归。而不是递归调用,使用堆栈。作为一个例子,阅读维基百科(http://en.wikipedia.org/wiki/Tree_traversal#Iterative_Traversal)上描述的迭代树递归示例。我会考虑消除堆栈的最佳选择。这意味着您可以处理任意复杂的图形,只能处理可用的内存而不是堆栈的大小。 – 2011-05-03 12:28:08