Java使用递归填充3D链接列表

时间:2016-01-04 10:13:51

标签: java list recursion nodelist

我在尝试填充3D链表时遇到堆栈溢出。我不明白为什么它不停在指定的界限,它只是永远运行。这可能是一个简单的错误,我只是不明白。

编辑:好的,我现在已经更新了代码并删除了这个愚蠢的错误,但它仍然没有完全按照预期运行。它似乎确实生成了10x10x10列表,但它无限运行。用(10,10,10)初始化,它应该创建10000个对象并停止。我只是想创建一个表示3d坐标平面的列表,每个整数坐标是一个节点,可以通过方向指针向北,向南,向东,向西,向上或向下访问。

任何帮助表示赞赏

import caffe, json
class myLayer(caffe.Layer):
  def setup(self, bottom, top):
    param = json.loads( self.param_str ) # use JSON to convert string to dict
    self.phase = param['phase']
    self.other_param = int( param['numeric_arg'] ) # I might want to use this as well...
编辑:好的,我现在已经更新了代码并删除了这个愚蠢的错误,但它仍然没有完全按照预期运行。它似乎确实生成了10x10x10列表,但它无限运行。用(10,10,10)初始化,它应该创建10000个对象并停止。我只是想创建一个表示3d坐标平面的列表,每个整数坐标是一个节点,可以通过方向指针访问。

3 个答案:

答案 0 :(得分:1)

您正在遇到无限递归。

所以发生了什么。

您正在创建新的Array

if(node.nodes == null) {
   node.nodes = new Node3D[5];
}

您继续使用Node3D作为newNode变量。发生这种情况是因为node.x<xMax将成立。 - &GT; Node3D newNode = node.nodes[2] = new Node3D();

您现在使用此pnc递归调用newNode

那么现在发生了什么,node.y<yMax将是真的。 现在你重新分配newNode。 Node3D newNode = node.nodes[0] = new Node3D();。 然后再次呼叫pnc。但是你现在遇到了问题。因为这是一个新的Node3D,你的node.x<xMax将再次成为现实,这两个步骤将再次发生并且无限,直到您收到上述错误为止。

要修复此错误,您可能需要将node.xnode.y复制到新创建的变量中。

通过更改赋值,您可以跳出无限递归。

if (node.x < xMax) {
    if (node.nodes[2] == null) {
        node.nodes[2] = new Node3D();
    }
    Node3D newNode = node.nodes[2];
    newNode.x = node.x + 1;
    newNode.y = node.y;
    newNode.z = node.z;

    pnc(newNode, xMax, yMax, zMax);
}
if (node.y < yMax) {
    if (node.nodes[0] == null) {
        node.nodes[0] = new Node3D();
    }
    Node3D newNode = node.nodes[0];
    newNode.x = node.x;
    newNode.y = node.y + 1;
    newNode.z = node.z;

    pnc(newNode, xMax, yMax, zMax);
}
if (node.z < zMax) {
    if (node.nodes[4] == null) {
        node.nodes[4] = new Node3D();
    }
    Node3D newNode = node.nodes[4];
    newNode.x = node.x;
    newNode.y = node.y;
    newNode.z = node.z + 1;

    pnc(newNode, xMax, yMax, zMax);
}

但是因为我不知道你想要在数组中的这些特定索引处使用这些特定元素,这对你来说可能是一个错误的解决方案。

答案 1 :(得分:1)

每当你创建一个新的Node3D时,变量x,y和z都没有被初始化,因此如果被访问它们将被评估为0.

在pnc方法中,总会出现x&lt; xMax,y&lt; yMax或z&lt; zMax,因为它们都被设置为1。

一个好的做法是尽可能将变量设为私有和最终:

class Node3D {
    private final Node3D[] nodes;
    private final int x;
    private final int y;
    private final int z;

    public Node3D(int x, int y, int z) {
        this.nodes = new Node3D[6];
        this.x = x;
        this.y = y;
        this.z = z;
    }
}

这将防止将来出现这类错误。您可以为变量创建getter方法。如果您确实需要重新分配x,y或z的值,则可以创建一个新的Node3D,以便该对象可以保持不变。

答案 2 :(得分:1)

您以多种方式导航到3D网格中的节点。例如,您从(1,0,0)和(0,1,0)都转到(1,1,0),为同一坐标创建重复项。这样,您可以创建多个节点,这些节点等于每个节点的总cube paths

另一种方法是填充节点的多维数据集,并为每个节点提供对它们所在的多维数据集的引用。然后当您需要向北时,您只需让多维数据集返回正确的节点,使用坐标当前节点。您可以使用Apache的MultiKeyMap作为网格:

class Node3D {
    private static int instances = 0;
    public final int x;
    public final int y;
    public final int z;
    public final int number;
    public final MultiKeyMap<Integer, Node3D> gridMap;

    public Node3D(MultiKeyMap<Integer, Node3D> gridMap, int x, int y, int z) {
        this.gridMap = gridMap;
        this.x = x;
        this.y = y;
        this.z = z;
        this.number = instances++;
    }

    //Add/alter these methods according to your orientation
    //Returns null if no value is present, you might want to handle this
    public Node3D getNorthNode() {
        return gridMap.get(this.x + 1, this.y, this.z);
    }

    //Other getters omitted

    @Override
    public String toString() {
        return "Node3D#" + number + "[" + x + ", " + y + ", " + z + "]";
    }
}

现在可以按如下方式进行初始化:

    MultiKeyMap<Integer, Node3D> gridMap = new MultiKeyMap<>();
    for(int x = 0; x < xMax; x++) {
        for(int y = 0; y < yMax; y++) {
            for(int z = 0; z < zMax; z++) {
                gridMap.put(x, y, z, new Node3D(gridMap, x, y, z));
            }
        }
    }

    System.out.println(gridMap.get(4, 4, 4).getNorthNode());