二叉排序树查找/删除(附完整测试用例)

二叉排序树删除思路:
  1. 若删除结点为叶子结点,可直接删除。
  2. 若删除结点左子树为空,那么右子树接上(俗称子承父业)。
  3. 若删除结点右子树有空,那么左子树接上(依旧是子承父业)。
  4. 若删除结点左右子树均不为空,那么有两种办法:
    第一种是直接按照上面的方法,直接左子树接上,然后将其右子树的结点再一个个插入,这样可能会引起树的高度增加,使得查询效率降低,故我们不采用这种方法。
    第二种方法是查找被删除结点A的直接前驱结点B或者是直接后继结点替代,为什么要找直接前驱或者直接后继呢?因为该结点不可能同时存在左子树和右子树,即将问题矛盾转化成上面已经处理过的问题,本文代码处采用直接前驱替代,直接前驱结点B在被删除结点的最左下方,我们找到直接前驱结点B,直接将B的数据替换被删除结点的数据,再将直接前驱结点B删除即可。
typedef struct BiTree{
    struct BiTree* lchild;
    struct BiTree* rchild;
    int data;
}BiTree;

//二叉排序树删除
bool BalDelete(BiTree* &bt){
    if (bt->lchild == NULL && bt->rchild == NULL) { //要删除的结点为叶子结点
        BiTree* p = bt;
        bt = NULL;
        delete p;
    }else if(bt->lchild == NULL){ //要删除的结点左指针为空
        BiTree* p = bt;
        bt = bt->rchild;
        delete p;
    }else if(bt->rchild == NULL){ //要删除的结点右指针为空
        BiTree* p = bt;
        bt = bt->lchild;
        delete p;
    }else{ //要删除的结点左右指针都非空
        BiTree* preParent = bt;
        BiTree* pre = bt->lchild; //转向左子树
        while(pre->rchild) { //向右走到尽头,寻找待删除结点的前驱
            preParent = pre;
            pre = pre->rchild;
        }
        bt->data = pre->data; //将直接前驱的数值代替要删除的结点
        if (preParent != bt) {
            preParent->rchild = pre->lchild;
        }else{
            preParent->lchild = pre->lchild;
        }
        delete pre;
    }
    return true;
}

//二叉排序树查找,调用删除
bool BalDeleteBST(BiTree* &bt,int data){
    if (bt == NULL) {
        return false;
    }
    if (bt->data == data) {
        return BalDelete(bt);
    }else if(bt->data < data){
        return BalDeleteBST(bt->rchild, data);
    }else{
        return BalDeleteBST(bt->lchild, data);
    }
}

//创建|插入二叉排序树
bool BalCreateTree(BiTree* &bt, int key){
    if (bt == NULL) {
        bt = new BiTree();
        bt->data = key;
        return true;
    }else{
        if(key == bt->data){
            return false;
        }else if (key > bt->data) {
            return BalCreateTree(bt->rchild, key);
        }else{
            return BalCreateTree(bt->lchild, key);
        }
    }
}

//查找
bool BalFindData(BiTree* bt,int key){
    if (bt == NULL) {
        return false;
    }
    if (key == bt->data) {
        return true;
    }else if(key > bt->data){
        return BalFindData(bt->rchild, key);
    }else{
        return BalFindData(bt->lchild, key);
    }
}

//中序遍历
void BiInOrder(BiTree* root){
    if (root == NULL) {
        return;
    }
    BiInOrder(root->lchild);
    cout<< root->data <<" ";
    BiInOrder(root->rchild);
}

int main(int argc, const char * argv[]) {
    BiTree* tree = NULL;
    int balData[] = {38,12,34,56,13,6,98,17,40,78};
    for (int i = 0; i < sizeof(balData)/sizeof(int); i++) {
        BalCreateTree(tree, balData[i]);
    }
    BiInOrder(tree);
    cout<<endl;
    BalDeleteBST(tree,40); //删除叶子结点40
    BiInOrder(tree);
    cout<<endl;
    BalDeleteBST(tree,34); //删除只有左子树
    BiInOrder(tree);
    cout<<endl;
    BalDeleteBST(tree,13); //删除只有右子树
    BiInOrder(tree);
    cout<<endl;
    BalDeleteBST(tree,38); //删除38,有左右子树(执行while)
    BiInOrder(tree);
    cout<<endl;
    BalDeleteBST(tree,12); //删除12,有左右子树(不执行while)
    BiInOrder(tree);
    cout<<endl;
    return 0;
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值