二叉排序树的增删查(C++)

这篇博客介绍了二叉搜索树(BST)的基本操作,包括查找、插入和删除节点的方法。首先定义了TreeNode结构体,然后分别实现了bstSearch()用于查找节点,bstInsert()用于插入节点,bstDel()用于删除节点。删除操作中考虑了叶子节点和非叶子节点的不同情况,并找到了替代节点。最后通过示例展示了如何在BST中进行这些操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <iostream>

using namespace std;
typedef struct TreeNode {
    int data;
    struct TreeNode *lchild;
    struct TreeNode *rchild;
} TreeNode;

//查找
TreeNode *bstSearch(TreeNode *T, int key) {
    if (T) {
        if (T->data == key) {
            return T;
        } else if (key < T->data) {
            return bstSearch(T->lchild, key);
        } else {
            return bstSearch(T->rchild, key);
        }
    } else {
        return nullptr;
    }
}

void preOrder(TreeNode *T) {
    if (T == nullptr) {
        return;
    }
    preOrder(T->lchild);
    cout << T->data << "  ";
    preOrder(T->rchild);
}

void bstInsert(TreeNode **T, int key) {
    if (*T == nullptr) {
        *T = (TreeNode *) malloc(sizeof(TreeNode));
        (*T)->data = key;
        (*T)->rchild = nullptr;
        (*T)->lchild = nullptr;
    } else if (key < (*T)->data) {
        bstInsert(&(*T)->lchild, key);
    } else if (key > (*T)->data) {
        bstInsert(&(*T)->rchild, key);
    } else {
        return;
    }
}

//查找父结点
TreeNode *searchFather(TreeNode *T, int key) {
    TreeNode *t = T;

    if (T == nullptr || T->data == key) {  //空树或者key为根节点的关键字
        return nullptr;
    }

    while (t->rchild || t->lchild) {  //有孩子

        if (key < t->data && t->lchild->data != key) {   //key值<该节点关键字 并且 key不是该节点的左孩子
            t = t->lchild;
        } else if (key > t->data && t->rchild->data != key) {   //key值>该节点关键字 并且 key不是该节点的右孩子
            t = t->rchild;
        } else if (key < t->data && t->lchild->data == key) {
            return t;
        } else if (key > t->data && t->rchild->data == key) {
            return t;
        }
    }
    return nullptr;
}



//删除操作中查找删除节点左子树的最大值,用来代替删除节点
TreeNode *del_find_lchild(TreeNode *T) {
    TreeNode *t = T;
    while (t->rchild) {
        t = t->rchild;
    }
    return t;
}


//删除操作中查找删除节点右子树的最小值,用来代替删除节点
TreeNode *del_find_rchild(TreeNode *T) {
    TreeNode *t = T;
    while (t->lchild) {
        t = t->lchild;
    }
    return t;
}

void bstDel(TreeNode **T, int key) {
    TreeNode *dt = bstSearch(*T, key); //找到要删除的节点


    if (dt) {  //存在该节点
       // TreeNode *df = del_find_lchild(dt); //要删除节点的父节点。
        TreeNode *df = searchFather(*T, key); //找到父亲节点
        if(df){  //如果有父节点
            if (dt->rchild == nullptr && dt->lchild == nullptr) { //该节点如果是叶子节点,直接删除

                //删除节点
                if (key < df->data) {
                    free(df->lchild);
                    df->lchild = nullptr;
                } else {
                    free(df->rchild);
                    df->rchild = nullptr;
                }


            } else {  //非叶子节点
                if (dt->lchild) {//左子树不为空
                    TreeNode *l_maxChild = del_find_lchild(dt->lchild);  //要删除节点的左子树中最大的节点
                    TreeNode *l_maxChild_f = searchFather(*T,l_maxChild->data);//要删除节点的左子树中最大节点的父节点

                    if(l_maxChild->data < l_maxChild_f->data){
                        l_maxChild_f->lchild = nullptr;
                    }else{
                        l_maxChild_f->rchild = nullptr;
                    }

                    l_maxChild->lchild = dt->lchild;
                    l_maxChild->rchild = dt->rchild;

                    if (key < df->data) {  //如果要删除的节点是其父节点的左孩子
                        df->lchild = l_maxChild;  //用要删除节点的左子树中最大的节点代替要删除的节点
                    } else {
                        df->rchild = l_maxChild;
                    }
                    free(dt);   //释放掉要删除节点的内存

                } else {   //右子树不为空

                    TreeNode *r_minChild = del_find_rchild(dt->rchild);  //要删除节点的右子树中最小的节点
                    TreeNode *r_minChild_f = searchFather(*T,r_minChild->data);//要删除节点的右子树中最小节点的父节点

                    if (r_minChild->data < r_minChild_f->data){
                        r_minChild_f->lchild = nullptr;
                    }else{
                        r_minChild_f->rchild = nullptr;
                    }

                    r_minChild->lchild = dt->lchild;
                    r_minChild->rchild = dt->rchild;


                    if (key < df->data) {  //如果要删除的节点是其父节点的左孩子
                        df->lchild = r_minChild;  //用要删除节点的左子树中最大的节点代替要删除的节点
                    } else {
                        df->rchild = r_minChild;
                    }

                    free(dt);   //释放掉要删除节点的内存

                }

            }
        }
        else{  //要删除的是根节点
            if(dt->lchild){ //左子树不为空
                TreeNode *l_maxChild = del_find_lchild(dt->lchild);
                TreeNode *l_maxChild_f = searchFather(*T, l_maxChild->data);

                if (l_maxChild->data < l_maxChild_f->data){   //把左子树最大的值删除
                    l_maxChild_f->lchild = nullptr;
                }else{
                    l_maxChild_f->rchild = nullptr;
                }

                l_maxChild->lchild = dt->lchild;  //把要删除节点的左右孩子复制到左子树最大的孩子上
                l_maxChild->rchild = dt->rchild;

                *T = l_maxChild;
                free(dt);

            }else{  //左子树为空
                *T = dt->rchild;
                free(dt);
            }

        }

    }

}




int main() {
    TreeNode *T = nullptr;
    int nums[9] = {7,5,15,4,6,12,18,9,13};
    for (int i = 0; i < 9; i++) {
        bstInsert(&T, nums[i]);
    }

    preOrder(T);  //中序遍历 4  5  6  7  9  12  13  15  18
    bstDel(&T,9);
    cout << endl;
    preOrder(T); 		 //4  5  6  7  12  13  15  18
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值