BST删除节点

首先,BST节点的删除分为几种情况:
(a)当该节点为 叶子节点,则让该节点的父节点指向其变为NULL,然后释放节点;
(b)当该节点 不是叶子节点,但 左子树或者右子树为空,则:
        (1)若左子树为空,则让该节点父节点指向其右节点;
        (2)若右子树为空,则让该节点父节点指向其左节点。
(c)当该节点 不是叶子节点,且 左子树和右子树都不为空,则:
        (1)在该节点的左子树中找到最大节点Lmax(该节点必然是一个叶子节点),取出Lmax的值val,删除Lmax;
        (2)将 val 赋给该节点的值,即:root->val = val。
        (3)判断Lmax的父节点PreLmax的左节点是否等于Lmax,若是则:PreLmax->left = Lmax->left    否则:  PreLmax->right = Lmax->left。
二叉搜索树的删除复杂度为O(h),h是二叉树的高度。代码如下:
/*删除二叉搜索树中的指定值的节点*/
node *deleteNode(node *root, int ele)
{
    node *newroot = root;  //指向新的根节点 
    node *presite = root; //指向要删除节点的父节点 
    int pos = 0; //要删除节点在其父节点的位置: -1:在左侧    1:在右侧    0:就是根节点  
    /*找到要删除的元素在BST中的位置*/ 
    while(root != NULL)
    {
        if(root->val > ele)
        {
            presite = root;
            root = root->left;
            pos = -1;
        }
        else if(root->val < ele)
        {
            presite = root;
            root = root->right;
            pos = 1;
        }
        else
        {
            break;            
        }
    }
    if(root == NULL)
    {
        cerr<<"要删除的节点不存在于BST中\n";
    }
    else
    {
        //该节点有左子树和右子树 
        if(root->left!=NULL && root->right!=NULL)
        {
            cout<<"has left and right tree\n";
            node *Lmax = root->left;    //最大左子节点 
            node *PreLmax = root;       //最大左子节点的父节点 
            while(Lmax->right != NULL)
            {
                PreLmax = Lmax;     
                Lmax = Lmax->right;
            }
            root->val = Lmax->val;    //替换root的值为最大左子树节点值
            if(PreLmax->left == Lmax)  //root的左子树最大节点是root的左节点 
                PreLmax->left = Lmax->left;
            else              //root的左子树最大节点不是root的左节点
                PreLmax->right = Lmax->left;
            delete Lmax;
            Lmax = NULL;
        }
        //该节点的左子树为空 
        else if(root->left == NULL && root->right != NULL)      
        {
            cout<<"left tree is empty\n";
            if(0 == pos)        //在根节点 
            {
                newroot = root->right;
            }
            else if(1 == pos)     //在右侧 
            {    
                presite->right = root->right;
            }
            else                  //在左侧 
            {
                presite->left = root->right;    
            }
            delete root;
            root = NULL;
        }
        //该节点的右子树为空 
        else if(root->right == NULL && root->left != NULL)     //site的右子树为空
        {
            cout<<"right tree is empty\n";
            if(0 == pos)      //在根节点 
            {
                newroot = root->left;
            }
            else if(1 == pos) //在右侧 
            {
                presite->right = root->left;
            }
            else                //在左侧 
            {
                presite->left = root->left;    
            }
            delete root;
            root = NULL;
        }
        //该节点为叶子节点 
        else                    
        { 
            cout<<"leaf node\n";
            if(0 == pos)          //根节点 
            {
                cerr<<"BST只有一个节点且被删除,该BST变为空树\n";
                delete root;
                root = NULL;
            }
            else if(1 == pos)      //在右侧 
            {
                presite->right = NULL;
                delete root;
                root = NULL;
            }
            else                  //在左侧 
            {
                presite->left = NULL;
                delete root;
                root = NULL;    
            }
        }    
    }
    return newroot;
}

 

转载于:https://www.cnblogs.com/ladawn/p/9325223.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值