我正在设计一个程序,用于搜索二维数字数组,这些数字表示指向指定终点的路径的地图。我一直在使用具有多个参数的节点,最突出的是相邻的北,南,东和西节点,每个节点代表地图中的正方形。我目前正在尝试完成的搜索方法是迭代加深,但每次尝试运行程序时,我都会遇到堆栈溢出错误。这是迭代深化课程。
import java.util.*;
import java.io.*;
public class IDeepeningSearch {
private Node start;
private Node end;
private int[][] map;
private ArrayList<Node> solution;
//Build using file handler
public IDeepeningSearch(String file){
FileHandler handle = new FileHandler(file);
//Create map
map = handle.getMap();
//Start node coordinates and value
start = new Node();
start.setRow(handle.getSRow());
start.setCol(handle.getSCol());
start.setValue(map[start.getRow()][start.getCol()]);
//End node coordinates
end = new Node();
end.setRow(handle.getERow());
end.setCol(handle.getECol());
end.setValue(map[start.getRow()][start.getCol()]);
}
//Runs search
public void run(){
int i = 0;
solution = new ArrayList<Node>();
//Value of i indicates depth to be explored; will increment with each failure
while(solution.isEmpty()){
search(start, i);
i++;
}
if(!solution.isEmpty()){
System.out.println("It worked.");
}
System.out.println("If you're not seeing the other message then it failed.");
}
//Building tree
public void build(Node head){
setNLeaf(head);
setSLeaf(head);
setELeaf(head);
setWLeaf(head);
// if(head.getNorth() != null){
// build(head.getNorth());
// }
// if(head.getSouth() != null){
// build(head.getSouth());
// }
// if(head.getEast() != null){
// build(head.getEast());
// }
// if(head.getWest() != null){
// build(head.getWest());
// }
}
//Performs search
public void search(Node head, int depth){
if(head.getRow() == end.getRow() && head.getCol() == end.getCol()){
solution.add(head);
return;
}
else{
if(depth == 0){
return;
}
build(head);
if(head.getNorth() != null){
search(head.getNorth(), depth--);
}
if(head.getSouth() != null){
search(head.getSouth(), depth--);
}
if(head.getEast() != null){
search(head.getEast(), depth--);
}
if(head.getWest() != null){
search(head.getWest(), depth--);
}
}
}
//Sets north leaf
public void setNLeaf(Node node){
//Determines if parent is on edge of map and if desired space has 0 value
if(node.getRow() != 0 && map[node.getRow() - 1][node.getCol()] != 0){
Node n = new Node();
n.setRow(node.getRow() - 1);
n.setCol(node.getCol());
n.setValue(map[n.getRow()][n.getCol()]);
n.setParent(node);
node.setNorth(n);
}
}
//Sets south leaf
public void setSLeaf(Node node){
//Determines if parent is on edge of map and if desired space has 0 value
if(node.getRow() != (map.length - 1) && map[node.getRow() + 1][node.getCol()] != 0){
Node n = new Node();
n.setRow(node.getRow() + 1);
n.setCol(node.getCol());
n.setValue(map[n.getRow()][n.getCol()]);
n.setParent(node);
node.setSouth(n);
}
}
//Sets east leaf
public void setELeaf(Node node){
//Determines if parent is on edge of map and if desired space has 0 value
if(node.getRow() != (map[0].length - 1) && map[node.getRow()][node.getCol() + 1] != 0){
Node n = new Node();
n.setRow(node.getRow());
n.setCol(node.getCol() + 1);
n.setValue(map[n.getRow()][n.getCol()]);
n.setParent(node);
node.setEast(n);
}
}
//Sets west leaf
public void setWLeaf(Node node){
//Determines if parent is on edge of map and if desired space has 0 value
if(node.getCol() != 0 && map[node.getRow()][node.getCol() - 1] != 0){
Node n = new Node();
n.setRow(node.getRow());
n.setCol(node.getCol() - 1);
n.setValue(map[n.getRow()][n.getCol()]);
n.setParent(node);
node.setWest(n);
}
}
}
我以为我正确地做到了这一点,但我所得到的错误一直都很稳定。这就是我最终的目标。
Exception in thread "main" java.lang.StackOverflowError
at Node.setSouth(Node.java:88)
at IDeepeningSearch.setSLeaf(IDeepeningSearch.java:113)
at IDeepeningSearch.build(IDeepeningSearch.java:48)
at IDeepeningSearch.search(IDeepeningSearch.java:75)
at IDeepeningSearch.search(IDeepeningSearch.java:77)
at IDeepeningSearch.search(IDeepeningSearch.java:80)
at IDeepeningSearch.search(IDeepeningSearch.java:77)
倒数第二行和最后一行重复。我已经尝试构建一个完整的树,但要么给我另一个堆栈溢出错误或空指针异常。我不确定这里的问题是什么,但如果我能解决这个问题,我相信我也可以完成我的广度优先搜索方法。
答案 0 :(得分:1)
depth--
评估depth
的原始值。这意味着未修改的depth
版本将被传递给search()
的递归调用,因此您的代码永远不会接近基本情况。请尝试使用depth-1
。或者,如果您需要更改局部变量深度的值,--depth
。
例如,这将持续打印10直到达到堆栈溢出
public void foo(int x) {
if (x == 0) {
return;
}
System.out.println(x);
foo(x--);
}
foo(10);
答案 1 :(得分:0)
StackOverflowError
是因为Chris Rise在答案中提到的search(node, depth--)
的有问题的递归调用。请尝试--depth
来解决此问题。
此代码中的内存管理也很差,这会浪费堆内存,这可能会因为多次调用GC(Garbage-Collector)而导致程序变慢或导致OutOfMemeoryError
!每次创建setXLeaf(Node n)
时,setNLeaf(Node north)
方法(例如new Node
等)都会显示此问题,而只有在需要进行简单检查时才能执行此操作:< / p>
if (node.getSouth() == null) {
Node n = new Node();
n.setParent(node);
node.setSouth(n);
}
node.getSouth().setRow(node.getRow() + 1);
node.getSouth().setCol(node.getCol());
node.getSouth().setValue(map[node.getRow() + 1][node.getCol()]);
这样您就可以避免创建不必要的新对象。这应该在所有setXLeaf(...)
方法中修复。