c++ 在二叉搜索树中删除

Posted

技术标签:

【中文标题】c++ 在二叉搜索树中删除【英文标题】:c++ delete in binary search tree 【发布时间】:2011-12-24 12:47:10 【问题描述】:

我有一个二叉搜索树,由如下节点组成:

struct ProductNode

    Product data;
    ProductNode* left;
    ProductNode* right;
;

我有一个带有 ProductNode 指针参数的删除函数:

void ProductCategory::deleteandnull(ProductNode * p) 

    if(p!=NULL)
    
        delete p;
        p=NULL;
    

我对删除方法没有任何问题。添加新叶子时左右指针为 NULL,但是当我使用此函数时,我看到没有删除,并且此操作不会更改二叉搜索树。这是什么问题?

【问题讨论】:

我说我对删除逻辑没有问题。我对他们没问题(一个孩子,两个孩子,没有孩子)我问为什么当我使用这个功能时没有删除。 er...因为函数错误:/ 所以你说这个功能没有问题,但你说它不工作。真的,在这里提问之前你应该先清醒一下:) Akın Yılmaz:“没有删除”。事实上,删除是正确的!查看我的答案了解详情 发布一些你将如何使用的代码。您可能应该考虑如何在 C++ 中传递函数参数。 【参考方案1】:

改用这个:

void ProductCategory::deleteRightChild(ProductNode * p) 

    if(p->right!=NULL)
    
        delete p->right;
        p->right = NULL;
    

为左孩子写一个等效的函数。

您的功能不起作用,因为您没有更改父节点的内容。它仍然具有已删除节点的地址,因此(如果此内容在其他地方重新分配并更改)它可以访问它...!

但是内存确实被释放了。

【讨论】:

【参考方案2】:

编辑:这个答案是基于 OP 得出结论“没有删除”的假设,因为他希望在调用位置看到一个 NULL 指针。如果不是这种情况,他将需要澄清导致该结论的原因。因为没有理由认为 OP 的代码没有删除 p 指向的任何内容。

p 按值传递给deleteandnull 函数。因此,只有指针的本地副本设置为NULL。假设你在某处有这样的代码:

ProductNode *ptr = // Somehow initialize to the parent of the node to delete
.
.
deleteandnull(ptr->left);

你需要在调用deletandnull之后添加这个

ptr->left = NULL;

请注意,在调用delete 之前不必测试NULL。它自己会这样做。而且由于deleteandnull 中的p 是本地的,因此将其设置为NULL 是没有意义的。所以整个代码还不如简化为:

ProductNode *ptr = // Somehow initialize to the parent of the node to delete
.
.
delete ptr->left;
ptr->left = NULL;

综上所述,在现代 C++ 中,您不应该使用裸指针 newdelete。更喜欢使用智能指针,例如在 Boost 库中。

【讨论】:

感谢兄弟,但即使我使用 delete p,它仍然没有删除; p=NULL;而不是 deleteandnull 函数。我在函数 deletespecified(paramaters) 中使用这个删除操作可能是因为这个函数还是因为一些 & 符号?【参考方案3】:
   Procedure :
   1. At first locate the node to be deleted.

   2. If the node is a leaf node :
   i. If the node is left child of the parent , make null the left pointer of its parent node and free the space for the node.
   ii. If the node is right child of the parent , make null the right pointer of its parent node and free the space for the node.

   3. If the node has one child
    i. If the node to be deleted is a left chile of its parent , then make link between the left pointer of its parent node and the child node to be deleted. Then delete the node.
    ii.If the node to be deleted is a right child of its parent , then make link between the right pointer of its parent node and the child node to be deleted. Then delete the node.

   4. If the node to be deleted has two child :
     i. Locate the node with maximum value from the left sub-tree of  the node to be deleted.
     ii. Replace the node value to be deleted by the node found in step 4(i)

   5. Now we get updated output

C++ 实现:

    node* Delete(node *root, int data)
    
      if(root == NULL) return root;

      else if(data < root->data) root->left = Delete(root->left,data);

      else if (data > root->data) root->right = Delete(root->right,data);

      else
      
       ///Case 1:  No child
      if(root->left == NULL && root->right == NULL)
      
        delete root;
        root = NULL;
      

      ///Case 2: One child
      else if(root->left == NULL)
      
        struct node *temp = root;
        root= root->right;
        delete temp;
      

      else if(root->right == NULL)
      
        struct node *temp = root;
        root = root->left;
        delete temp;
      

      ///case 3: 2 children
       else
       
         node *temp = FindMin(root->right);
         root->data = temp->data;
         root->right = Delete(root->right,temp->data);
       
     
    return root;  

【讨论】:

请正确地将您的文本格式化为文本,并将您的代码格式化为代码。 我已经正确格式化了我的代码。请关注代码而不是格式。如果您发现错误,您会通知我。 @Marcus Müller 请检查我的答案。

以上是关于c++ 在二叉搜索树中删除的主要内容,如果未能解决你的问题,请参考以下文章

二叉搜索树

在二叉搜索树中查找地板和天花板

在二叉搜索树中找到一个节点的父节点

为啥我的代码不能在二叉搜索树中正确执行预排序?

删除二叉搜索树中的节点会引发错误

在二叉搜索树中查找中位数的错误