简体   繁体   English

二叉搜索树节点删除问题

[英]Problem Deleting Node of a Binary Search Tree

I am implementing a binary search tree in C ++, but the code has an error, when deleting a node with 2 children the resulting tree is not well connected, the method to delete a node with 0 or 1 child works well.我正在用C++实现一个二叉搜索树,但是代码有错误,当删除一个有2个孩子的节点时,结果树没有很好地连接,删除一个有0个或1个孩子的节点的方法效果很好。 This code is based in this answer: https://stackoverflow.com/a/31698320/11053027 .此代码基于此答案: https : //stackoverflow.com/a/31698320/11053027

Edit: For example if a add the values in this order: 17, 12, 25, and then I try delete 17 that is the root, it is deleted, so when I try to show all the elements are: 12, 25, with 25 as root.编辑:例如,如果按以下顺序添加值:17、12、25,然后我尝试删除作为根的 17,它将被删除,因此当我尝试显示所有元素时:12、25、 25 作为根。 But if now I try to delete 12 it is not deleted, the problem is caused when I first deleted 17. No error message is shown.但是如果现在我尝试删除 12 它没有被删除,问题是在我第一次删除 17 时引起的。没有显示错误消息。

Can you help me please.你能帮我吗。 Thanks in advance.提前致谢。 Here is the code:这是代码:

    Node<E> *getSuccesor(Node<E> &node) const {
       auto *Succesor = node.right;
       while (Succesor != nullptr) {
          if (Succesor->left == nullptr) return Succesor;
          Succesor = Succesor->left;
       }
       return Succesor;
    }

    void remove(Node<E> &node) {
       if (&node == nullptr) return;
       int nChildren = numChildren(node);
       Node<E> *child;

       if (nChildren == 2) {
        child = getSuccesor(node);
        remove(*child);
        child->parent = node.parent;
        child->left = node.left;
        child->right = node.right;
        if (&node == root)
            root = child;
        else {
            if (&node == node.parent->right)
                node.parent->right = child;
            else node.parent->left = child;
        }
    } else {
        child = (node.left != nullptr ? node.left : node.right);

        if (child != nullptr)
            child->parent = node.parent;

        if (&node == root)
            root = child;
        else {
            if (&node == node.parent->left)
                node.parent->left = child;
            else node.parent->right = child;
        }
    }
    Size--;
 }

It's hard to be certain, since you haven't given us a minimal complete example , but I think the problem is here:很难确定,因为你没有给我们一个最小的完整例子,但我认为问题出在这里:

if (nChildren == 2) {
  child = getSuccesor(node);
  remove(*child);
  child->parent = node.parent;
  child->left = node.left;
  child->right = node.right;

So now child knows its children.所以现在child知道它的孩子。 But they don't know that child is now their parent.但是他们不知道那个child现在是他们的父母。 Their parent pointers still point to the defunct node (in this case, '17'), which messes up the logic in the next removal.它们的parent指针仍然指向已失效的节点(在本例中为“17”),这会在下一次删除时弄乱逻辑。

After those lines, add these:在这些行之后,添加这些:

if(child->left)
  child->left->parent = child;
if(child->right)
  child->right->parent = child;

EDIT: The same bug is also in the other branch of the if-else conditional, but I'm sure you can see how to fix it there too.编辑:同样的错误也在 if-else 条件的另一个分支中,但我相信你也可以在那里看到如何修复它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM