【问题标题】:BST removing node with 2 children not deleting predecessorBST 删除具有 2 个子节点的节点不删除前任
【发布时间】:2020-05-09 22:04:33
【问题描述】:

我正在从 BST 中删除节点。它目前适用于没有孩子或只有一个孩子的所有情况。当我去删除一个有 2 个子节点的节点时,该节点会被删除,但前任值不会更改为 null,因为我觉得代码说明了这一点,但没有任何变化。

   public Node(String w, Node p, Node l, Node r) {
         //value = v;
         word = w;
         parent = p;
         left = l;
         right = r;
      }
   public void remove(String target) {
      if (root == null) {
         return;
      }
      if (root.word.compareTo(target) == 0)
      {
         removeRoot(target);
      }
      else {
         removeNonRoot(target);
      }
   }
   private void removeNonRoot(String target) {

      Node cur = root;
      Node parent = null;

      while (cur != null) {
         if (cur.word.compareTo(target) == 0) {
            break;
         }
         if (target.compareTo(cur.word) < 0) {
            if (cur.left != null) {
               parent = cur;
               cur = cur.left;
            }
         }
         else if (target.compareTo(cur.word) > 0) {
            if (cur.right != null) {
               parent = cur;
               cur = cur.right;
            }
         }
      }
     if (cur.left == null && cur.right == null)
      {
         if (parent.left != null && parent.left.word.compareTo(target) == 0) {
            parent.left = null;
         }
         else if (parent.right != null && parent.right.word.compareTo(target) == 0)
         {  
            parent.right = null;
         }
      }
      else if (cur.left == null && cur.right != null) {
         if (parent.right != null && parent.right.word.compareTo(target) == 0) {
            parent.right = cur.right;
         }
         else if (parent.left != null && parent.left.word.compareTo(target) == 0) {
            parent.left = cur.right;
         }
      }
      else {
         Node temp = findPredecessor(target, parent);
         cur.word = temp.word;
      }
   }
private void removeRoot(String target) {
   // only root
      if (root.left == null && root.right == null)
      {
         root = null;
         return;
      }
      // right child
      else if (root.left == null)
      {
         root = root.right;
         return;
      }
      // left child
      else if (root.right == null)
      {
         root = root.left;
      }
      // 2 children
      else
      {
         Node temp = findPredecessor(target, root);
         root.word = temp.word;
         return;
      }
   }

private Node findPredecessor(String s, Node start) {
      Node parent = start;
      Node child = start.left;

      if (child == null) {
         return parent;
      }
      else if (child != null) {
         while (child.right != null) {
            child = child.right;
         }
         Node temp = child;
         child.right = null;
         return temp;
      }
      else {
         return null;
      }
}

如果我有一个按以下顺序插入字符的 bst:e -> f -> c -> a -> d 尝试删除 c 的结果将返回 c 所在的 d,以及 d 的右子树,应该是 d。

这会让我相信问题出在我之前调用 child.right = null 的方法中。我认为实际上并没有分配该值,但不确定为什么。 拆除结果图:

【问题讨论】:

标签: java binary-search-tree


【解决方案1】:

遵循整个逻辑以及您想要实现的目标有点困难,但是,在您的代码中初步通过,我认为主要问题是您没有更新节点上的父信息。

例如:当您将cur.right 分配给parent.rightparent.left 时,您还应该更新parent.right 上的parent 以正确反映父节点。

else if (cur.left == null && cur.right != null) {
   if (parent.right != null && parent.right.word.compareTo(target) == 0) {
      parent.right = cur.right;
   } else if (parent.left != null && parent.left.word.compareTo(target) == 0) {
      parent.left = cur.right;
   }
   // Update parent information of `cur.right`
   cur.right.parent = parent;
}

您应确保更新逻辑中的所有此类实例,以便所有子节点正确反映其父节点。

【讨论】:

  • 我正在尝试处理我有两个子节点并且需要用正确的子节点替换该节点的情况。它将右孩子向上移动,并移除父节点,但不会摆脱右孩子的值/节点。
【解决方案2】:

归结为添加 2 行代码。在 removeNonRoot 作为 else 块的最后一行

cur.right = null;

然后在最后一个 else if 块中的 removeRoot 内

removeNonRoot(temp.word);

如果根节点有 2 个子节点,父节点有 2 个子节点且根节点不为空,这在这两种情况下都会有所不同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-26
    相关资源
    最近更新 更多