【问题标题】:Java - Binary Tree pointer still null after initialization?Java - 初始化后二叉树指针仍然为空?
【发布时间】:2016-05-03 10:18:26
【问题描述】:

这个问题非常抽象,因此很难描述或搜索,这就是我在这里的原因。然而,这是一个非常简单的问题。

我有以下课程:

class Node<T>
{
    Comparable data;
    Node<T> left, right;

    public Node(Comparable data)
    {
        this.data = data;   
    }
}

如果我有会发生什么:

/*
* Imagine this root looks like the following:
*       10 (root)
*       /       \
    null        null
*/
Node root;

// Imagine we are inside of the insert method and this
// is the current value that is going to be inserted.
int valueIAmTryingToInsert = 5;

// As we see from the tree above, "child" WILL be null.
Node child = (valueIAmTryingToInsert.compareTo(root.data) < 0 ? root.left : root.right);

if (child == null)
{
    child = new Node(data);
    return true;    
}

// Recursive statement would happen here.

请注意,child 是指向root 的左子或右子的指针。但是,如果我实例化 child 指向的节点会发生什么?调用child = new Node(data);后,树目前是不是这样:

    10 (root)
    /       \
    5       null

如果它不看起来像那样,请解释原因。因为我的理解是即使Node child 为空,指针仍然 指向root 的其中一个孩子。我很确定这不起作用,因为我的编辑在声明child = new Node(data); 中强调了child 并声称The value new Node(data) assigned to 'child' is never used(即使它正在被使用)。

【问题讨论】:

  • 这实际上是一种更简单的方式来描述我的问题。为什么THIS 会产生空指针异常? second 指向 first,它最初为 null,但随后成为一个初始化对象,因此应该正确指向它。
  • 根节点还没有初始化?所以 root.data 会抛出 NPE。另外,您创建了一个子节点但尚未附加到根节点?
  • 根据您的评论,当您调用“new”时,您正在为该对象在内存中创建一个 NEW 引用。 Null 是没有参考的。这就是为什么, second 和 first 指向 null,但是当你实例化 first 时, second 仍然指向 null,然后 second.x 抛出 NPE
  • @MinhKieu 我不想写出一棵完全成熟的树,所以就假装root 已经初始化并且有很多孩子,等等。
  • @aquiros 但是second 指向变量first。这应该意味着无论first 发生什么,它都应该记住first 在内存中的位置。你是说当我打电话给first = new ... 时,它实际上改变了内存位置,不再是以前的位置了吗?

标签: java data-structures binary-tree nodes


【解决方案1】:

你永远不会将它分配给根节点作为它的“左”。

简而言之,这就是您的代码的作用:

-根的左边(或右边)是否为空? -是的 - 请创建一个新节点。

但是这个新节点和根节点之间没有关联。 你可能需要这样的东西:

Node root;
Node child;
Integer valueIAmTryingToInsert = 5;
if(valueIAmTryingToInsert.compareTo(root.data) < 0){
    if(root.left == null){
        root.left = new Node(valueIAmTryingToInsert);
    }
    child = root.left;
}else{
    if(root.right == null){
        root.right = new Node(valueIAmTryingToInsert);
    }
    child = root.right;
}
return true;    

编辑: 此代码只是一个示例,但如果root.data 为空,您将得到一个NullPointerException,因为比较。您可能会意识到并注意这一点。

编辑 2: 我可以看到您仍然感到困惑,主要问题是您必须记住 null 不是对对象的引用。它是一个“标记”,表示对象还没有被初始化。所以当我说a = null; b = a 不像a 和b 指向同一个对象时(因为null 不是一个有效的对象或引用),这意味着它们都还没有被初始化。它们是独立的独立变量。然后,当我初始化一个 a = new MyClass() 时,我要求为 a 提供内存引用,但 b 仍然指向内存中的任何位置。

请参阅null 来表达“这个对象没有指向任何地方”。 如果事情如你所想(如果我初始化a 那么b 也应该指向那里);那么程序中的每个空对象都应该指向a 现在指向的位置。

【讨论】:

  • @Hatefiend 这将是解决问题的适当方法。如果您仍想使用三元运算符,仍然可以在最终 if-conditional 中创建 child 后将其分配给 root.left 或 root.right
  • 看,我试图避免嵌套 if 语句。我有点理解你最初的解释,但不是真的。我只是不明白。 root.left 指向 child(在这种情况下)。然后我更改了child,但root.left 仍然认为child 为空。这没有任何意义。
  • 关于您的编辑,我的实际代码比这要详细得多,所以不用担心我已经处理了任何 null 问题。这是唯一的阻碍。
  • @Hatefiend 你说 root.left 在哪里指向孩子(在这种情况下)?
  • 等等等等……我搞糊涂了。抱歉——我的主要误解是在我的 OP 中,为什么 child 仍然为空。这对我来说毫无意义。
【解决方案2】:

您需要了解child = new Node() 将更改您的指针指向的对象,而不是指针之前指向的对象的任何值,也绝对不会更改其他指针指向的对象(如root.left)。

root.left 和 child 不是同一个变量,即使在调用 child = root.left 之后也是如此!它们只指向同一个对象。因此,改变一个指向的内容不会影响另一个。

基本上,new Node() 在您的记忆中某处创建一个新对象。 child = new Node() 做同样的事情,除了之后它告诉变量 child 指向那个新创建的对象,而不是它之前指向的任何对象。

【讨论】:

  • 感谢您的回复。 > root.left 和 child 不是同一个变量 root.left 指向Node,我说Node child,指向root.left 指向的同一个节点。他们怎么能不指向同一个Node?
  • 他们是。只是一旦你说 child = 不管你让 child 指向不同的节点。
  • 想象告诉一个人看一辆蓝色的汽车。然后告诉第二个人看第一个人正在看的任何东西。然后,您创建了一辆新的红色汽车并告诉第二个人看它。现在第一个人在看什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-19
  • 2015-08-04
  • 2019-03-01
  • 2021-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多