正在查看一个SO问题,我建议递归填充节点网格,我认为我应该为自己尝试代码,以下内容不断溢出
public class Node {
private Node left;
private Node right;
private Node up;
private Node down;
private int x;
private int y;
public Node(int x, int y) {
this.x = x;
this.y = y;
}
public static void buildGrid(Node node) {
fill(node);
}
private static void fill(Node node) {
fillLeft(node);
fillRight(node);
}
private static void fillRight(Node node) {
if (node.right != null || node.x > 10)
return;
node.right = new Node(node.x + 1, node.y);
fill(node.right);
}
private static void fillLeft(Node node) {
if (node.left != null || node.x <= 0)
return;
node.left = new Node(node.x - 1, node.y);
fill(node.left);
}
public static void main(String[] args) {
Node node = new Node(5, 5);
buildGrid(node);
}
已经太晚了,我可能已经错过了非常明显但为什么会溢出?第一次fillLeft
返回fill(node.left)
时,对fillLeft(node.left)
的第二次调用应立即从node.left.right != null
开始返回。同样的fillRight
,无法弄清楚这里有什么问题。
堆栈跟踪
Exception in thread "main" java.lang.StackOverflowError
at Node.<init>(Node.java:16)
at Node.fillLeft(Node.java:42)
at Node.fill(Node.java:26)
at Node.fillRight(Node.java:35)
at Node.fill(Node.java:27)
at Node.fillLeft(Node.java:43)
at Node.fill(Node.java:26)
at Node.fillRight(Node.java:35)
at Node.fill(Node.java:27)
at Node.fillLeft(Node.java:43)
at Node.fill(Node.java:26)
at Node.fillRight(Node.java:35)
at Node.fill(Node.java:27)
at Node.fillLeft(Node.java:43)
at Node.fill(Node.java:26)
at Node.fillRight(Node.java:35)
at Node.fill(Node.java:27)
at Node.fillLeft(Node.java:43)
at Node.fill(Node.java:26)
at Node.fillRight(Node.java:35)
at Node.fill(Node.java:27)
at Node.fillLeft(Node.java:43)
at Node.fill(Node.java:26)
at Node.fillRight(Node.java:35)
at Node.fill(Node.java:27)
at Node.fillLeft(Node.java:43)
答案 0 :(得分:3)
您的问题是您没有正确创建新节点之间的链接。你想要:
private static void fillRight(Node node) {
if (node.right != null || node.x > 10)
return;
node.right = new Node(node.x + 1, node.y);
node.right.left = node; // CURRENT NODE IS LEFT OF NEW NODE!
fill(node.right);
}
private static void fillLeft(Node node) {
if (node.left != null || node.x <= 0)
return;
node.left = new Node(node.x - 1, node.y);
node.left.right = node; // CURRENT NODE IS RIGHT OF NEW NODE!
fill(node.left);
}
如果打印出当前节点的坐标,您可以看到它向左移动并振荡,因为链接“返回”始终为null
。将其添加到fill()
的开头,看看发生了什么:
private static void fill(Node node) {
System.out.println("filling node " + node.x + " " + node.y +
" " + node.left + " " + node.right);
...
其次:递归网格填充变得混乱,很容易导致高递归深度和快速溢出。使用这些类型的东西,你最好使用队列而不是递归。
答案 1 :(得分:1)
从fillRight()
拨打fillRight()
,同样从左侧拨打电话。
目前正在创建一个新节点,然后在此节点上调用fill()
,该节点具有空左/右指针......
答案 2 :(得分:1)
你的fillLeft和fillRight将永远不会遇到条件node.left!= null和node.right!= null这将停止递归。
看起来x和y是你的密钥,你必须在某处根据x和y存储它们并在它们已经创建时检索它们而不是总是调用新节点。