【问题标题】:Binary Search Tree- deleting a node causes other methods errors c++二叉搜索树-删除节点会导致其他方法错误c ++
【发布时间】:2021-02-21 09:32:45
【问题描述】:

我在从 BST 中删除节点时遇到问题。我写了一个搜索节点的方法,效果很好,当我试图删除一个叶子时(到目前为止我写的唯一情况)它会导致错误 (0xDDDD...)在印刷方法上。我认为这是因为打印方法遇到某种空值,但我不知道如何解决这个问题。这是代码... 按值方法删除节点:

void deleteNodeByValue(T val)
{
    cout << "\nElement to delete: " << val << " \n";
    Node<T>* tmp = root;
    while (tmp != NULL)
    {
        if (val == tmp->data)
        {
            cout << "Element found: " << tmp->data << " \n";

            if (tmp->right_child == NULL && tmp->left_child == NULL)
            {
                delete tmp;
                tmp = NULL;
                size--;
            }

            break;
        }
        else if (val > tmp->data)
        {
            tmp = tmp->right_child;
        }
        else if (val < root->data)
        {
            tmp = tmp->left_child;
        }
    }      
}

和树打印:

string to_string()
{
    stringstream ss;
    Node<T>* tmp = root;
    queue<Node<T>*> q;

    while (!q.empty() || tmp != NULL)
    {
        if (tmp != NULL)
        {
            q.push(tmp);
            tmp = tmp->left_child; //debugger shows error in this place
        }
        else
        {
            tmp = q.front();
            q.pop();
            ss << "Data: " << tmp->data;
            if (tmp->left_child != NULL)
            {
                ss << " Left child: " << tmp->left_child->data;
            }
            if (tmp->right_child != NULL)
            {
                ss << " Right child: " << tmp->right_child->data;
            }
            ss << " \n";
            tmp = tmp->right_child;
        }
    }
    return ss.str();

它还会导致其他方法出现错误,例如获取树高或按顺序获取树等。 我该怎么办?

【问题讨论】:

  • 你应该做的是重新开始。这个损坏的代码无法以任何合理的方式修复。至少有两个基本缺陷:节点被删除,但来自其父节点的指针保持不变,因此迭代 BST 最终将取消引用垃圾指针making demons fly out of your nose。只有当它是叶节点时它才会被删除,而当它不是叶节点时不会发生任何事情。这显然也是错误的。树需要重新平衡,这是很多代码,无处可寻。这是无法修复的。从头开始。
  • @SamVarshavchik 我的印象是 BST(与 RB 树或类似树相反)不能保证是平衡的,因此不需要在删除后重新平衡。
  • 好吧,@MikeVine,为了删除非叶节点,需要重新平衡某些东西,或者需要做一些事情。但是显示的代码绝对没有任何作用。
  • 我想我认为重新平衡是在删除或插入之后完成的事情 - 保证树保持平衡。删除不需要这样做 - 尽管我同意它确实需要做更多的工作并且写错了

标签: c++ search tree binary nodes


【解决方案1】:

很简单,你删除了节点,但是那个节点的父节点仍然指向它。因此,您正在尝试打印已删除的节点。

您必须记住谁是您删除的节点的父节点,并将其更新为不再指向它。

有很多方法可以做到这一点,如果我是你,我个人会将tmp 设为双指针,但由于你的名字是newbie,这里的解决方案更容易阅读:

cout << "\nElement to delete: " << val << " \n";
Node<T>* tmp = root;
Node<T>* parent = NULL;
while (tmp != NULL)
{
    if (val == tmp->data)
    {
        cout << "Element found: " << tmp->data << " \n";

        if (tmp->right_child == NULL && tmp->left_child == NULL)
        {
            if (parent == NULL) root = NULL;
            else {
                if (parent->right_child == tmp) {
                    parent->right_child = NULL;
                } else {
                    parent->left_child = NULL;
                }
            }
            delete tmp;
            size--;
        }

        break;
    }
    else if (val > tmp->data)
    {
        parent = tmp;
        tmp = tmp->right_child;
    }
    else if (val < root->data)
    {
        parent = tmp;
        tmp = tmp->left_child;
    }
}    

当然你还得加上node不是叶子的情况的处理,不过好像明白了。

【讨论】:

  • 谢谢!现在我明白了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-18
  • 1970-01-01
相关资源
最近更新 更多