如何编写递归实例方法来检查二叉树在结构上是否与另一个二叉树相同?

时间:2017-05-24 04:25:50

标签: java recursion tree binary-tree

所以今天我的数据结构最终有一个考试问题:

"考虑BinaryTree类并添加两个名为compBT的递归方法(彼此独立)来比较两个二叉树。如果两个二叉树在结构上相同(即,当忽略存储在节点中的对象时它们看起来相同),则两个方法中的每一个都返回true;否则,每个返回false。第一种方法应该是实例方法,第二种方法应该是类方法。不要直接访问底层数据结构。注意:每个方法不应超过6行并正确缩进。"

我能够为类方法生成这个:

  public static boolean compareTrees(BinaryTree t1, BinaryTree t2) {
      if (t1 == null && t2 == null) return true;
      if ((t1 == null && t2 != null) || (t1 != null && t2 == null)) return false;

      return compareTrees(t1.left, t2.left) && compareTrees(t1.right, t2.right);
  }

我对这个答案非常有信心,但编写实例方法让我感到非常难过,特别是因为它必须独立于类方法。我能够制作的所有内容如下:

public boolean compareTrees(BinaryTree t) {
    if (t == null) return false;
    return (compareTrees(this.left) && (t.left)) && (compareTrees(this.right) && compareTrees(t.right));
}

我知道这个方法是不正确的,因为它总是会返回false,因为只有一个基本情况会永远满足。我在特定基本情况背后的思考过程是,如果参数为null,则返回false,因为存在结构不等式,因为调用者不能为null(只有非空引用才能调用实例方法)。但我不知道该怎么办。

有人可以加入吗?我认为这个问题非常有趣。

编辑:添加BinaryTree类。

这里是BinaryTree类的样子:

class BinaryTree {
    public int value;
    public BinaryTree left;
    public BinaryTree right;

    public BinaryTree(int x) { value = x;}
}

2 个答案:

答案 0 :(得分:0)

我认为您已经认识到了基本问题。在静态方法中,当您以递归方式调用方法时,可以为两个子树传递null。但是在您的实例方法中,您只能对参数执行此操作。您无法为实例方法执行此操作,因为您无法在null上调用实例方法。

好吧,如果你不能在null子项上递归调用实例方法,则必须在递归调用之前处理null子case 。这是关键,你必须重新安排你的逻辑。所以你的逻辑必须是这样的:

  1. 如果参数为null,则返回false(就像您已经做过的那样)

  2. 如果实例的左子项为null,则:

    2.1如果参数的左子项不为null,则返回false

    2.2如果参数的左子项为空,请继续执行步骤4

  3. 如果实例的左子项不为null,则以递归方式对左子项进行调用(如果参数的左子项为null,则无关紧要,因为这将是捕获为#1),如果递归调用返回false,则返回false

  4. 4-5。适合孩子的步骤

    1. 如果我们已经走到这一步,并且没有检查失败,那么我们可以返回真实
    2. 所以代码看起来像这样:

        public boolean compareTrees(BinaryTree t) {
            if (t == null) return false;
            if (this.left == null) {
                if (t.left != null) {
                    return false;
                }
            } 
            else if (!this.left.compareTrees(t.left)) {
                return false;
            }
            if (this.right == null) {
                if (t.right != null) {
                    return false;
                }
            } 
            else if (!this.right.compareTrees(t.right)) {
                return false;
            }
            return true;
        }
      

      编辑:我刚才注意到该方法要求不超过6行。所以我想我的答案不会奏效。另一方面,我可以通过将一堆东西压缩到几行来使其工作。

        public boolean compareTrees(BinaryTree t) {
            if (t == null) return false;
            if (this.left == null && t.left != null) return false;
            if (this.left != null && !this.left.compareTrees(t.left)) return false;
            if (this.right == null && t.right != null) return false;
            if (this.right != null && !this.right.compareTrees(t.right)) return false;
            return true;
        }
      

      通过将最后两行合二为一,我可以缩短它。但 如果你的教授要奖励像这样的压缩,难以阅读的代码,并且像我之前的例子中那样使用清洁代码失败,那么就会感到羞耻。

      更多:好的,如果你的教授通过较少的行来测量代码质量,这应该让他欣喜若狂,即使我的所有同事都会在代码审查中对其进行爆炸:

        public boolean compareTrees(BinaryTree t) {
            return !((t == null) || (this.left == null && t.left != null) ||  (this.left != null && !this.left.compareTrees(t.left)) || (this.right == null && t.right != null) || (this.right != null && !this.right.compareTrees(t.right)) );
        }
      

答案 1 :(得分:0)

例如方法,所有改变的是检查在递归之前,否则在其中:

  public boolean compareTrees(BinaryTree other) {

      if (left == null) != (other.left == null) return false;
      if (right == null) != (other.right == null) return false;

      if (left != null && !left.compareTrees(other.left)) return false;
      if (right != null && !right.compareTrees(other.right)) return false;

      return true;
  }