【问题标题】:BST delete - delete "tmp" causes lose of the treeBST 删除 - 删除“tmp”会导致树丢失
【发布时间】:2020-11-02 15:59:52
【问题描述】:

debug result

附上我试图在 bst 中删除节点的代码。

如果我想删除节点1,当在“if (del_node->l_ == NULL)”中指定tmp = del,并删除tmp时,del也被删除,树数据丢失。我该如何解决这个问题?

示例树:

  3
 / \
1   5
 \ 
  2
  • 为简单起见,所有数据成员和函数都声明为 public。

      void BST::DeleteNode(int data) {
          BinaryTreeNode* &del_node = BST_Search(head_, data);
          if (!del_node->l_ && !del_node->r_)
          {
              delete del_node;
              del_node = nullptr;
              return;
          }
          if (del_node->l_ == NULL)
          {
              BinaryTreeNode* tmp = del_node;
              del_node = del_node->r_;
              tmp = nullptr;
              delete tmp;
              return;
          }
          if (del_node->r_ == NULL)
          {
              BinaryTreeNode* tmp = del_node;
              del_node = del_node->l_;
              delete tmp;
              return;
          }
          else
          {
              del_node->data_ = smallestRightSubTree(del_node->r_);
          }
    
      }
    
      int BST::smallestRightSubTree(BinaryTreeNode* rightroot)
      {
          // if rightroot has no more left childs
          if (rightroot && !rightroot->l_)
          {
              int tmpVal = rightroot->data_;
              BinaryTreeNode* tmp = rightroot;
              rightroot = rightroot->r_;
              delete tmp;
              return tmpVal;
          }
          return smallestRightSubTree(rightroot->l_);
      }
      int main()
      {
          BST bst;
          bst.BST_Insert(bst.head_, 3);
          bst.BST_Insert(bst.head_, 5);
          bst.BST_Insert(bst.head_, 1);
          bst.BST_Insert(bst.head_, 2);
          bst.DeleteNode(1);
          return 0;
      }
    

感谢您的帮助! 编辑:这是条件“if(del->l = null)”中的“del_node = del_node->r_)”行之后 tmp 和 del_node 的样子

void BST::BST_Insert(BinaryTreeNode*& head, int data) {
if (head == nullptr) {
    head = new BinaryTreeNode(data, nullptr, nullptr);
    return;
}
if (data > head->data_) {
    BST_Insert(head->r_, data);
}
else {
    BST_Insert(head->l_, data);
}

}

BinaryTreeNode* BST::BST_Search(BinaryTreeNode* root, int key) {
    if (root == nullptr || root->data_ == key)
        return root;
    if (key > root->data_)
        return BST_Search(root->r_, key);
    return BST_Search(root->l_, key);
}

【问题讨论】:

  • tmp = nullptr; delete tmp; 不释放任何内存。它只是忘记了 tmp 中指针的值。不确定“树数据丢失”是什么意思。您可能应该为此使用调试器并观察该方法的运行情况。或者做一个正确的minimal reproducible example,这样我们就可以看到问题了。或两者兼而有之。
  • 感谢您的评论。去掉“tmp=nullptr”,事情是,树是按我预期的那样构造的。但是,当我在删除方法中时,“del_node”获取节点 1 的地址,“tmp”获取与 del_node 相同的内存地址。当 del_node 被提升为指向它的右子节点时,del_node 和 tmp 中的数据被删除.. (可能是错误使用了 delete 运算符?)在原始帖子中附加了调试器的屏幕截图。谢谢
  • 如果在这段代码之后 del_node 指向可能是堆栈的空白,那么怀疑将落在BST_Search 没有做完全正确的事情并且您还没有向我们展示其中的内容.对minimal reproducible example 的要求不仅仅是为了给您带来不便,还有一个意义……
  • 对不起!没注意。也添加了这些功能。仍在尝试了解什么不起作用.. 是不是与我删除指针的脸有关?也许因为他们拥有相同的地址,删除一个会导致另一个删除?过去两个小时我一直在调试这个,但由于某种原因,del_node 和 tmp 在“delete tmp”行之后变为空

标签: binary-search-tree


【解决方案1】:

如果您的BST_Search 按值返回BinaryTreeNode*,那么BinaryTreeNode* &del_node = BST_Search(head_, data); 中的实际引用是什么?它分配一个新的临时并引用它。您可能希望它引用保存树中指针的变量,以便您可以修改树。

您的 BST_Search 必须如下所示:

BinaryTreeNode*& BST::BST_Search(BinaryTreeNode*& root, int key) {
    if (root == nullptr || root->data_ == key)
        return root;
    if (key > root->data_)
        return BST_Search(root->r_, key);
    return BST_Search(root->l_, key);
}

我无法检查这是否真的有效,因为您没有提供一个独立的可编译示例。但是有些类似的东西。

【讨论】:

  • 谢谢,它有效!我一直在调试这几个小时!你能解释一下为什么在搜索中没有引用指针的版本不起作用吗?我以为这就是你返回地址的方式......再次感谢你!
  • 想象一下,如果您想删除 root(bst.root?不确定您如何命名它)。您希望能够更改 root 变量内的指针值。如果您使用旧搜索来搜索它,您会得到它的值(指向第一个节点的指针)。你能用这个值给root变量分配一个不同的指针值吗?您需要获得对变量的引用才能做到这一点,而不仅仅是它的值。
  • 另一种观点:您的del_node 是一个副本。当你改变它时,你只是改变你的副本,而不是原件。您需要以某种方式获取对原始文件的引用。
猜你喜欢
  • 2017-01-02
  • 2021-04-03
  • 2018-07-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-13
  • 1970-01-01
  • 2012-08-06
  • 1970-01-01
相关资源
最近更新 更多