所以今天我的数据结构最终有一个考试问题:
"考虑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;}
}
答案 0 :(得分:0)
我认为您已经认识到了基本问题。在静态方法中,当您以递归方式调用方法时,可以为两个子树传递null
。但是在您的实例方法中,您只能对参数执行此操作。您无法为实例方法执行此操作,因为您无法在null
上调用实例方法。
好吧,如果你不能在null子项上递归调用实例方法,则必须在递归调用之前处理null子case 。这是关键,你必须重新安排你的逻辑。所以你的逻辑必须是这样的:
如果参数为null,则返回false(就像您已经做过的那样)
如果实例的左子项为null,则:
2.1如果参数的左子项不为null,则返回false
2.2如果参数的左子项为空,请继续执行步骤4
如果实例的左子项不为null,则以递归方式对左子项进行调用(如果参数的左子项为null,则无关紧要,因为这将是捕获为#1),如果递归调用返回false,则返回false
4-5。适合孩子的步骤
所以代码看起来像这样:
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;
}