【问题标题】:Inverting/Mirroring a Binary Tree. Method isn't leaving the input tree intact?反转/镜像二叉树。方法没有使输入树完好无损?
【发布时间】:2015-07-14 19:52:25
【问题描述】:

我是 Java 新手(只编程了一个月),所以我一直在练习一些概念。因此,如果这是一个幼稚或愚蠢的问题,请耐心等待我。我以前只在 MATLAB 中编程过!

我刚刚成功地反转了一棵二叉树(我也是第一次尝试!)。但是,我很困惑为什么我的方法实际上是在修改我作为输入传递的树,而不是让它保持原样并简单地返回一个倒置的变体。简而言之,在我的主要功能中的以下行之后:

inverse = invertBinaryTree(root);

'inverse' 和 'root' 都是相等的,并且在我将 'root' 传递给方法 'invertBinaryTree' 之前,它们是 'root' 的反转版本。拜托,我在试图理解这种行为时失去理智!

事实上,我什至尝试创建辅助方法“invertBinaryTree2”,这个变体将输入复制到占位符节点并在占位符节点而不是输入上进行操作;但是,这无济于事,我的输入仍然改变!

这是我的第一个完整的主要功能和支持功能。 invertBinaryTree 和 invertBinaryTree2 的行为方式相同,即使我将 root 复制到占位符变量中!

public class leetCode_InvertBinaryTree {

public static void main(String[] args) {
    /*
     * initializing some binaryNodes for the tree
     */
    binaryNode a = new binaryNode(4);
    binaryNode b = new binaryNode(2);
    binaryNode c = new binaryNode(7);
    binaryNode d = new binaryNode(1);
    binaryNode e = new binaryNode(3);
    binaryNode f = new binaryNode(6);
    binaryNode g = new binaryNode(9);
    binaryNode inverse;
    
    /*
     * just building the tree
     */
    a.left = b;
    a.right = c;
    b.left = d;
    b.right = e;
    c.left = f;
    c.right = g;
    
    /*
     * Here is the issue!
     */
    System.out.println("Before inverting, root's left branch contains: " + a.left.data);
    inverse = invertBinaryTree(a);
    System.out.println("After inverting, root's left branch contains: " + a.left.data);
    System.out.println("After inverting, inverse's left branch contains: " + inverse.left.data);
}

public static binaryNode invertBinaryTree(binaryNode root){
    if(root.right == null && root.left == null){
        return root;
    }
    else if(root.right == null){
        root.right = root.left;
        root.left = null;
    }
    else if (root.left == null){
        root.left = root.right;
        root.right = null;
    }
    else {
        binaryNode temp = root.left;
        root.left = root.right;
        root.right = temp;
    }
    root.left = invertBinaryTree(root.left);
    root.right = invertBinaryTree(root.right);
    return root;
}

public static binaryNode invertBinaryTree2(binaryNode root){
    binaryNode placeholder = root;
    if(placeholder.right == null && placeholder.left == null){
        return placeholder;
    }
    else if(placeholder.right == null){
        placeholder.right = placeholder.left;
        placeholder.left = null;
    }
    else if (placeholder.left == null){
        placeholder.left = placeholder.right;
        placeholder.right = null;
    }
    else {
        binaryNode temp = placeholder.left;
        placeholder.left = placeholder.right;
        placeholder.right = temp;
    }
    placeholder.left = invertBinaryTree(placeholder.left);
    placeholder.right = invertBinaryTree(placeholder.right);
    return root;
}

没关系,但这里是 binaryNode 类,以防它帮助你帮助我。我还包括了我在上面发布的 main 函数的输出。

在反转之前,根的左分支包含:2

反相后,root的左分支包含:7

反转后,inverse的左分支包含:7

public class binaryNode {

public int data;
public binaryNode left;
public binaryNode right;

/*
 * constructor for binaryNode
 */
public binaryNode(int d){
    data = d;
}}

【问题讨论】:

  • 您应该查找references and how they are handled when passed as an argument to a method。长话短说:在方法 invertBinaryTree(...) 中,您正在修改您传递给方法的原始树。
  • @Turing85 感谢您的及时回复!这怎么可能呢?当我将根传递给该方法时,该方法不是简单地“复制”根而不是在真正的根上操作吗?
  • 阅读链接。这一切都在那里解释。 This question 也与此主题相关。如果克隆了root,方法调用会非常慢(想象一棵有数千个节点的树,因为树是递归数据结构,你必须克隆树中的每个节点......)。

标签: java tree pass-by-reference


【解决方案1】:

我建议您添加更多调试语句(例如在 println 中)以显示代码每个阶段的结构状态。这将有助于向您说明代码在做什么。

你的问题的原因是:

在这个方法中:

public static binaryNode invertBinaryTree(binaryNode root){

...您正在传递节点,一个指向 binaryNode 类对象的指针(引用)。 **顺便说一句,大多数样式约定都要求您将其称为更像 BinaryNode 的东西(大写是标准化的)...

在类 binaryNode 的这一行中:

public binaryNode left;

...您将节点“left”声明为任何人都可以修改的成员。该成员属于“binaryNode”类型,这意味着它引用“binaryNode”类型的对象的地址。

在这段代码中:

else if (root.left == null){
    root.left = root.right;

...您正在将名为“left”的字段设置为 binaryNode 的地址,将其设置为“right”返回的内容,即另一个 binaryNode 的地址。

...等等。您正在设置引用的值,因此正在更改数据结构的结构。

【讨论】:

  • 引用不等同于指针,Java中没有指针。
  • 引用确实是指针,只是减少了避免错误的能力。你不能对它们进行指针运算,你不能将它们转换成你想要的任何东西,等等。 @图灵85
  • @lamsomeone 所以你看......曾经的用户是管理员,他/她不能做任何事情......你基本上是这么说的:存在差异。仅仅因为引用是通过指针实现的,并不意味着它们指针。
  • @Turing85 :您想对 MATLAB 中的指针/引用发表意见吗?
  • @MonkeyWidget 我们正在谈论Java。 MATLAB 与此有什么关系?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-10-02
  • 2019-05-04
  • 1970-01-01
  • 2019-04-29
  • 1970-01-01
  • 2021-01-30
  • 1970-01-01
相关资源
最近更新 更多