【问题标题】:Return statement not working correctly from loop循环中的返回语句无法正常工作
【发布时间】:2017-10-07 00:34:10
【问题描述】:

我正在做一个涉及平衡二叉树的项目,但遇到了一些问题。

对于我项目的一部分,我想查看一棵树(或子树)并比较所述子树左孩子路径和右孩子路径的最大长度。如果这些路径的最大长度之间的绝对差大于 1,我想返回找到的第一个具有此属性的节点。逻辑有点简单..例如,如果我有树:

我的算法将查看 64 并比较沿左侧和右侧向下的路径长度(分别为 5 和 4)。这不会创建一个标志,因为差异是 1。然后我会递归地查看 64 的孩子。首先它会查看 43,然后转到 26。在 26 之后(因为它的每个子节点到叶子的长度为 1),算法将移动到 62。此时将抛出一个标志,因为 62s 左路径有一个长度3,它没有正确的路径。这是我想退出循环并返回 62 的地方。但是,我的循环继续运行,直到它检查最终节点。

如您所见,算法继续运行并返回一个空节点,而不是我想要的节点。我不确定它为什么这样做,但我认为它与优先级和范围有关。具体算法代码如下:

    public BinaryNode<Integer> NodeCheck(BinaryNode<Integer> Node) throws IllegalStateException
    {
        System.out.println("CHECKING NODE: " + Node.getData());

        int leftHeight = 0;
        int rightHeight = 0;

        if (Node.hasLeft())
        {
            leftHeight = 1 + findHeight(Node.getLeft());
        }

        if (Node.hasRight())
        {
            rightHeight = 1 + findHeight(Node.getRight());
        }
        System.out.println("LEFT HEIGHT = " + leftHeight);
        System.out.println("RIGHT HEIGHT = " + rightHeight);

        int z = Math.abs(leftHeight - rightHeight);
        if (z > 1)
        {
            System.out.println();
            System.out.println();
            System.out.println("PROBLEM DETECTED AT NODE " + Node.getData() + " ATTEMPTING TO RETURN NODE");
            BinaryNode<Integer> flag = createNode(Node.getData(), Node.getParent(),Node.getLeft(), Node.getRight());

            return flag;
        }

        for (BinaryNode<Integer> c : children(Node))
            {
                if (findHeight(c) > 1 && z<= 1)
                    {NodeCheck(c);}
            }


        return createNode(0,null,null,null);

    }

我认为重要的是要注意我最终处理了 if (z > 1) 语句中的信息,因为 System.out.println() 语句已执行,这使我相信 return 语句已执行。但是,这并没有像我想象的那样退出函数。

【问题讨论】:

    标签: java recursion scope


    【解决方案1】:

    问题是,您递归调用此方法,但没有检查。

    您应该更改以下内容以使其工作:

    • 最终的return 应该返回null
    • 在之前的循环中,您应该检查返回的值,如果不是null,则返回它。

    所以你方法的最后一部分应该是这样的:

        for ( final BinaryNode<Integer> c : children( node ) )
        {
            if ( findHeight( c ) > 1 && z <= 1 )
            {
                final BinaryNode<Integer> res = nodeCheck( c );
                if ( null != res )
                    return res;
            }
        }
        return null;
    }
    

    运行它会产生以下输出:

    CHECKING NODE: 64
    LEFT HEIGHT = 5
    RIGHT HEIGHT = 4
    CHECKING NODE: 43
    LEFT HEIGHT = 3
    RIGHT HEIGHT = 4
    CHECKING NODE: 26
    LEFT HEIGHT = 2
    RIGHT HEIGHT = 2
    CHECKING NODE: 62
    LEFT HEIGHT = 3
    RIGHT HEIGHT = 0
    
    
    PROBLEM DETECTED AT NODE 62 ATTEMPTING TO RETURN NODE
    

    【讨论】:

    • 谢谢!!这修复了错误
    • 应该提一下,如果没有检测到“问题”,这个版本可以在最后返回null...
    • 我明白了 - 该功能与我的功能逻辑完全一致。谢谢。
    【解决方案2】:

    我认为您的问题来自您在 for 循环中调用 NodeCheck() 的位置。我假设当您说if (findHeight(c) &gt; 1 &amp;&amp; z &lt;=1) 时,您的意思是说"if the child node has a height greater than 1 and 'z' has not yet been found to be greater than 1, then check the said child node"

    但是,当您第一次(在根目录上)运行它时,如果此时 z NodeCheck()那个根(即 43 和 92)。因此,即使它在左侧找到一个 z > 1 的节点,同样的检查也已经被请求到右侧,这就是为什么当左侧返回时它不会停止。

    这里有一个 for 循环的替代方案:您可以沿着一条路走,然后等着看是否在这条路上找到任何东西,然后再走另一条路。 你的代码变成了

    public BinaryNode<Integer> NodeCheck(BinaryNode<Integer> Node) throws IllegalStateException
    {
        System.out.println("CHECKING NODE: " + Node.getData());
    
        int leftHeight = 0;
        int rightHeight = 0;
    
        if (Node.hasLeft())
        {
            leftHeight = 1 + findHeight(Node.getLeft());
        }
    
        if (Node.hasRight())
        {
            rightHeight = 1 + findHeight(Node.getRight());
        }
        System.out.println("LEFT HEIGHT = " + leftHeight);
        System.out.println("RIGHT HEIGHT = " + rightHeight);
    
        int z = Math.abs(leftHeight - rightHeight);
        if (z > 1)
        {
            System.out.println();
            System.out.println();
            System.out.println("PROBLEM DETECTED AT NODE " + Node.getData() + " ATTEMPTING TO RETURN NODE");
            BinaryNode<Integer> flag = createNode(Node.getData(), Node.getParent(),Node.getLeft(), Node.getRight());
    
            return flag;
        }
    
        /*EDIT STARTS HERE*/
    
        if (Node.hasLeft() && findHeight(Node.getLeft()) > 1) //Check in the left node and see if it returns a flag
        {
            BinaryNode<Integer> left = Node.getLeft();
            BinaryNode<Integer> result = CheckNode(left);
    
            //If 'result' is null, then there was no flag, otherwise it found a flag. So check for that
            if (result != null)
            //If this condition is met, then result is a flag and the left child
            //found a z > 1. So cut the operations here and just return the same
            //flag to the one who called 'CheckNode()' on this 'Node'. 
            {return result;}
        }
    
        if (Node.hasRight() && findHeight(Node.getRight()) > 1) //Check in the right node and see if it returns a flag
        {
            BinaryNode<Integer> right = Node.getRight();
            BinaryNode<Integer> result = CheckNode(right);
    
            //Same as above
            if (result != null)
            //If this condition is met, then result is a flag and the right
            //child found a z > 1. So cut the operations here and just return
            //the same flag to the one who called 'CheckNode()' on this 'Node'. 
            {return result;}
        }
    
        /*EDIT ENDS HERE*/
    
        return null;
    
    }
    

    请注意,当您对孩子调用 CheckNode() 时,您不需要检查 z &lt;= 1,因为如果 z 大于 1,它会在您检查标志的块中返回并退出做System.out.println() 的事情。

    最后返回null 看起来更容易,因此您只需查看返回值就知道它是否找到标志(将是一个 BindaryNode 对象)或没有(将为空)。

    【讨论】:

    • 您认为它来自我的 for 循环是绝对正确的。在您的答案(以及上面的答案)中,您提供了一个变量来存储 CheckNode() 的返回值(例如 BinaryNode result = checkNode(left))。我认为标志节点将被传递给最初调用函数的环境,而不管 CheckNode 是否在函数本身内被递归调用。我没有意识到对 CheckNode 的递归调用会将标志值传递给 CheckNode() 环境,而这又需要传递给外部环境。
    猜你喜欢
    • 1970-01-01
    • 2021-05-30
    • 2014-09-27
    • 1970-01-01
    • 1970-01-01
    • 2015-03-14
    • 2020-09-20
    • 2012-08-21
    • 1970-01-01
    相关资源
    最近更新 更多