简体   繁体   English

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

[英]How to handle deep recursion when working with ArrayLists?

So earlier today I ran into an issue and now it's evening-time and all I've successfully done is identify the source of the issue. 所以今天早些时候我遇到了一个问题,现在是晚上时间,我所做的一切都是确定问题的根源。

在此输入图像描述

I have a bunch of nodes that make up a figure. 我有一堆构成数字的节点。 These nodes can also have node-children of their own (think shoulder->elbow->hand). 这些节点也可以有自己的节点子节点(想想肩 - >肘 - >手)。 A possible scenario for this figure is that one of these nodes may have attached to it many, many generations of descendant nodes (as pictured). 这个图的一个可能的情况是这些节点中的一个可能已经连接了许多代子节点(如图所示)。

The problem I'm having is if I run a typical recursive function like updatePosition() when the root node is moved, this function iterates down its line of children and eventually I get a StackOverflowError. 我遇到的问题是,如果我在移动根节点时运行像updatePosition()这样的典型递归函数,这个函数会迭代它的子行,最终得到一个StackOverflowError。

The problem I have is I don't know how to get around this limitation. 我遇到的问题是我不知道如何解决这个限制。 I understand I have to abandon this recursive method, but, how? 我明白我必须放弃这种递归方法,但是,怎么样? I'd really appreciate some input/advice to point me in the right direction. 我真的很感激一些意见和建议,指出我正确的方向。

Also note, this issue is occurring on Android devices, I'm assuming this leaves me with a relatively lower Stack limit than on a typical desktop JVM. 另请注意,此问题发生在Android设备上,我假设这使我的堆栈限制相对低于典型的桌面JVM。


Edit: According to dangVarmit solution of using a manually-created Stack, here's what I've come up with. 编辑:根据使用手动创建的堆栈的dangVarmit解决方案,这是我想出的。 I haven't been able to test this code yet, but it seems like it would work. 我还没有能够测试这段代码,但似乎它会起作用。

OLD CODE 旧代码

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();
}

NEW CODE 新代码

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...
}

Create a stack or ArrayList of nodes. 创建节点的堆栈或ArrayList。 push the root object onto the stack and then start a while loop (for stack not empty) 将根对象推入堆栈然后启动while循环(堆栈不为空)

the body of the loop operates on the top node of the stack. 循环体在堆栈的顶部节点上运行。 At any point where you would have recursed into the function you will now push the new node onto the stack and then use continue to begin the loop over on the new top level node. 在您已经递归到函数的任何时候,您现在将新节点推送到堆栈,然后使用continue在新的顶级节点上开始循环。

When the recursive function is done with a certain node it pops the node off the stack and calls continue to begin the loop over. 当递归函数与某个节点完成时,它会将该节点从堆栈中弹出并继续调用以开始循环。

Your loop needs to account for the fact that it may be called several times on the same node so you want to manage the state a little more. 您的循环需要考虑到它可能在同一节点上多次调用的事实,因此您希望稍微管理一下状态。 In a recursive function you would return to the parent caller in the same place in the function with the same state (local variables, etc) You lose that so you have to manage that state your self. 在递归函数中,您将返回到具有相同状态(局部变量等)的函数中相同位置的父调用者。您将失去该函数,因此您必须自己管理该状态。 In a left, right child node, you would need to remember that you checked and processed the left node so you can skip that on the second pass and check/process the right node this time (or pop the stack and continue if you've done both nodes) 在左右子节点中,您需要记住您已检查并处理了左侧节点,因此您可以在第二次传递时跳过该节点并在此次检查/处理正确的节点(或弹出堆栈并继续,如果您已经完成两个节点)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM