Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用ArrayList时如何处理深度递归?_Java_Android_Recursion_Stack Overflow - Fatal编程技术网

Java 使用ArrayList时如何处理深度递归?

Java 使用ArrayList时如何处理深度递归?,java,android,recursion,stack-overflow,Java,Android,Recursion,Stack Overflow,所以今天早些时候我遇到了一个问题,现在是晚上,我所成功做的就是找出问题的根源 我有一堆节点组成一个图形。这些节点也可以有自己的节点子节点(想想肩->肘->手)。此图的一个可能场景是,其中一个节点可能连接了很多代的后代节点(如图所示) 我遇到的问题是,如果我在移动根节点时运行一个典型的递归函数,如updatePosition(),该函数将沿着其子节点行进行迭代,最终得到一个StackOverflower错误 我的问题是我不知道如何绕过这个限制。我知道我必须放弃这种递归方法,但是,怎么做呢?我非常

所以今天早些时候我遇到了一个问题,现在是晚上,我所成功做的就是找出问题的根源

我有一堆节点组成一个图形。这些节点也可以有自己的节点子节点(想想肩->肘->手)。此图的一个可能场景是,其中一个节点可能连接了很多代的后代节点(如图所示)

我遇到的问题是,如果我在移动根节点时运行一个典型的递归函数,如updatePosition(),该函数将沿着其子节点行进行迭代,最终得到一个StackOverflower错误

我的问题是我不知道如何绕过这个限制。我知道我必须放弃这种递归方法,但是,怎么做呢?我非常感谢您的意见/建议,为我指明正确的方向

还要注意的是,这个问题发生在Android设备上,我假设这使得我的堆栈限制比典型桌面JVM上的堆栈限制要低



编辑:根据使用手动创建堆栈的dangVarmit解决方案,以下是我的想法。我还没有能够测试这段代码,但它似乎可以工作

旧代码

void validatePosition()
{
    if (_positionIsDirty == true)
        updatePosition();
}

void updatePosition()
{
    _positionIsDirty = false;
    // etc...

    for (int i = _childrenNodes.size() - 1; i >= 0; --i)    // This recursive part caused the StackOverflowError
        _childrenNodes.get(i).updatePosition();
}
void validatePosition()
{
    if (_positionIsDirty == true)
    {
        // Create a Stack and add this Node to it.
        Stack stack = new Stack();
        stack.push(this);

        while (stack.empty() == false)
        {
            // Pop top-most Node in Stack.
            Node node = stack.pop();

            // Update it and push its children onto the Stack.
            node.updatePosition();
            for (int i = node._childrenNodes.size() - 1; i >= 0; --i)
                stack.push(node._childrenNodes[i]);

        }
    }
}

void updatePosition()
{
    _positionIsDirty = false;
    // etc...
}
新代码

void validatePosition()
{
    if (_positionIsDirty == true)
        updatePosition();
}

void updatePosition()
{
    _positionIsDirty = false;
    // etc...

    for (int i = _childrenNodes.size() - 1; i >= 0; --i)    // This recursive part caused the StackOverflowError
        _childrenNodes.get(i).updatePosition();
}
void validatePosition()
{
    if (_positionIsDirty == true)
    {
        // Create a Stack and add this Node to it.
        Stack stack = new Stack();
        stack.push(this);

        while (stack.empty() == false)
        {
            // Pop top-most Node in Stack.
            Node node = stack.pop();

            // Update it and push its children onto the Stack.
            node.updatePosition();
            for (int i = node._childrenNodes.size() - 1; i >= 0; --i)
                stack.push(node._childrenNodes[i]);

        }
    }
}

void updatePosition()
{
    _positionIsDirty = false;
    // etc...
}

创建节点的堆栈或数组列表。将根对象推到堆栈上,然后启动while循环(对于堆栈非空)

循环体在堆栈的顶部节点上运行。在您将递归到函数中的任何点上,您现在将新节点推送到堆栈上,然后使用continue在新的顶级节点上开始循环

当对某个节点执行递归函数时,它会将该节点从堆栈中弹出,并继续调用以开始循环


您的循环需要考虑一个事实,即它可能会在同一个节点上被多次调用,因此您需要对状态进行更多的管理。在递归函数中,您将返回到函数中相同位置的父调用方,该调用方具有相同的状态(局部变量等),因此您必须自己管理该状态。在左、右子节点中,您需要记住您检查并处理了左节点,这样您就可以跳过第二次检查并处理右节点(或者,如果您已经完成了两个节点,则弹出堆栈并继续)

您可能希望在Wikipedia中查找“树遍历”,因为你要做的就是按预定顺序遍历一棵树。这篇文章有递归和非递归实现的例子。我认为@dangVarmint的答案基本上与文章的答案相同。是的,非常肯定。。你基本上是在用自己的堆栈替换系统堆栈,因为你可以分配比默认堆栈指针更多的内存。我还不能测试代码,但根据你的建议(如果我理解正确的话),如果我没有忽略任何东西的话,下面是我在一个quick.txt文件中提出的建议,我认为这可能会起作用(在开篇文章中更新)。