【问题标题】:Java object cannot passed by ref through recursionJava 对象不能通过递归通过 ref 传递
【发布时间】:2015-07-21 06:07:25
【问题描述】:

问题是我需要编写一个函数来验证二叉树是否是有效的二叉搜索树

这是我的代码:

public static boolean betterValidBSTArray(TreeNode node) {
    WrapInt lastData = null;
    return validate(lastData, node);
}

private static boolean validate(WrapInt lastData, TreeNode node) {
    if(node == null) return true;
    if(!validate(lastData, node.getLeft())) return false;
    if(lastData != null && node.getData() <= lastData.value) return false;
    if(lastData == null) lastData = new WrapInt();
    lastData.value = node.getData();
    if(!validate(lastData, node.getRight())) return false;

    return true;
}

class WrapInt { int value; }

问题是,这个算法不起作用。我设置了一些断点并发现对于每个堆栈调用,在堆栈调用完成后将 lastData 分配给一个值之后,上一个堆栈调用将继续 lastData = null,即使 lastData 对上一个堆栈调用具有实际值。

感谢您的帮助。

【问题讨论】:

  • 覆盖'WrapInt'类的克隆,然后在每次递归调用验证方法时尝试传递'lastData'对象的克隆。

标签: java recursion binary-search-tree


【解决方案1】:

要修复您的代码,您不应该执行if(lastData == null) lastData = new WrapInt();,因为它将对新对象的引用仅分配给方法调用参数,该参数是每个堆栈调用的局部变量,您不应将null 作为lastData 传递但将在整个递归中使用的对象,仅更改其value。

【讨论】:

    【解决方案2】:

    您对引用的工作方式做出了错误的假设。

    public static boolean betterValidBSTArray(TreeNode node) { WrapInt lastData = null; 返回验证(lastData,节点); }

    您似乎认为这会将lastData的地址向下传递以进行验证,并在触发正确的条件时将其设置为对象。

    但这真正的作用是:

       return validate(null, node);
    

    因为 lastData 的值 = null。

    您必须通过底层方法传递要填充的对象,因为引用总是按值传递。 (因此,您将值 null 向下传递,而不是像在 c++ 中执行 &lastData 那样传递 lastData 变量的地址)。

    如需更好的解释,请参阅the answers here

    解决方案是在外部创建引用,然后将其传递到您的方法中使用。

    public static boolean betterValidBSTArray(TreeNode node) {
         WrapInt lastData = new WrapInt();
         return validate(lastData, node);
    } 
    

    如果您想区分 null/not null(如果这在您的代码中有意义,例如找到它),您可以使用

    class WrapInt {
        Integer value;
    }
    

    或

    class WrapInt {
        private int value;
        private boolean set;
        public boolean wasSet() { return set; }
        public int getValue() { return value; } 
        public void setValue(int value) { this.value = value; set = true; }
    }
    

    这样递归外的代码就可以访问这个状态信息了。

    【讨论】:

      【解决方案3】:

      您需要在 betterValidBSTArray 中创建 WrapInt() 对象并将 null 分配给它的值。这样,您将传递 lastData 引用。试试这个,它会起作用的。

      【讨论】:

      • 将null 分配给原语?
      猜你喜欢
      • 2011-12-12
      • 1970-01-01
      • 1970-01-01
      • 2017-03-02
      • 2011-05-02
      • 1970-01-01
      • 1970-01-01
      • 2019-01-19
      • 1970-01-01
      相关资源
      最近更新 更多