【问题标题】:Issue with tree node reference being overwritten in Java在 Java 中覆盖树节点引用的问题
【发布时间】:2018-11-26 09:47:29
【问题描述】:

我目前正在为一个项目构建一个 ScapeGoatTree。但是,我在让我的重建功能正确掌握它正在构建的替罪羊节点时遇到问题。在下面的代码中,您将在“if(height >alpha height)”语句中看到另外 2 个 if 语句。第一个 if 语句比较了我的替罪羊节点(我知道它与当前测试数据应该是静态 root.left 节点)并且它正确地说它们是相等的。但是,当我尝试更改占位符节点(希望它是对 root.left 的对象引用)时,它只会覆盖我的占位符节点。因此,第二个 if 语句不会触发,但我需要 FindScapeGoat 的返回值作为正在编辑的节点。

我不会撒谎我一直不太善于理解语言中的引用传递和值传递差异,但我确实需要弄清楚如何在不需要的情况下正确地将更改应用于 root.left对它的特定调用(因为函数不会总是选择 root.left 作为替罪羊节点,我需要一种方法来调用我的树中以静态位置为根的各种节点)。

public static void Insert(int key) {
    height = dupflag = 0;
    root = insertHelp(root, key);
    if(dupflag == 0) MaxNodeCount++;    //If inserted value wasn't duplicate increase max node count
    double alphaHeight = ((Math.log(MaxNodeCount) / Math.log(1 / alpha)) + 1);
    if (height > alphaHeight){
        Node ToBeRebalanced = FindScapegoat(root, key);  // Find scapegoat node
        int sizeRoot = TreeSize(ToBeRebalanced, 0);
        if(ToBeRebalanced == root.left) System.out.println("Scapegoat node == root.left");
        ToBeRebalanced = RebuildTree(sizeRoot+1, ToBeRebalanced);
        if(ToBeRebalanced == root.left) System.out.println("Scapegoat node == root.left");
        Print(ToBeRebalanced);
        Print(root);
    }
}

【问题讨论】:

  • 我喜欢 90% 的方式来理解你想要什么。没有做你想要的方法RebuildTree?如果是这样,您可以发布代码吗?如果没有,你能试着澄清一下哪里出了问题吗?我了解您遇到的高级问题,但不是您的代码中具体体现的地方。另外,PlaceholderToBeRebalanced 是同一个东西吗?
  • 本质上,我想要这一行:“Node ToBeRebalanced = FindScapegoat(root, key);”或更重要的是,“FindScapeGoat(root, key);”的返回成为被编辑的对象.我知道在我当前的测试数据中 FindScapeGoat 将返回“root.left”,并且我将占位符节点 ToBeRebalanced 设置为等于“root.left”,但是该行中的 3 行:“ToBeRebalanced = RebuildTree(sizeRoot+1, ToBeRebalanced );" ToBeRebalanced 持有者节点会覆盖自身,而不是像我想要的那样直接写入 root.left。

标签: java binary-tree


【解决方案1】:

为了解决值/引用问题:Java 中的非原始变量的行为(主要是,超出此答案范围的大警告)就像指向内存位置的指针。当您说ToBeReplaced 时,您正在更改ToBeReplaced 指向的内存地址。

对于您更具体的问题,有几种方法可以解决此问题。我处理它的方式是更改FindScapegoat 的返回值,以指示节点是左还是右。它似乎只检查直接子节点,因此无需返回对节点本身的引用。

类似这样的:

public enum Side {
    LEFT,
    RIGHT
}
//...
Side ToBeRebalanced = FindScapegoat(root, key);  // Find scapegoat node
if (ToBeRebalanced == Side.Left){
  int sizeRoot = TreeSize(root.left, 0);
  root.left = RebuildTree(sizeRoot+1, root.left);
} else {
  int sizeRoot = TreeSize(root.right, 0);
  root.right = RebuildTree(sizeRoot+1, root.right);
}

然后您可以将 TreeSize 调用移动到 RebuildTree 方法中以避免重复代码。

【讨论】:

  • 或多或少地引导我找到正确的解决方案。由于我的树的高度超过 2,所以我不得不做更多的事情,然后在此处调用 root.left / root.right。但是我能够使用一般的想法让 FindScapegoat 返回父节点到实际的替罪羊节点,然后让我的引用指向修复了我的问题的返回节点子节点。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多