C++实现BST(二叉搜索树)的构建与增删查

BST的查询:

这里给出的是递归的写法(在树和链表中递归写法很常见也很容易理解,这里就不多赘述)

TreeNode* BST::BSTsearch(TreeNode* node , int val){
    if(!node){return nullptr;}
    if(node->val == val){
        return node;
    }
    return node->val >val ? BSTsearch(node->left, val) : BSTsearch(node->right, val);
}

BST的插入:

由于要插入的节点不存在,所以需要使用上一级的节点,将新的节点接入即可。

bool BST::BSTinsert(TreeNode* node , int val){
    TreeNode* next = node;
    TreeNode* newnode =new TreeNode(val);
    while(next){
        if(val<next->val){
            if(!next->left){
                next->left = newnode;
                return true;
            }else{
                next = next->left;
            }
        }else if(val>next->val){
            if(!next->right){
                next->right = newnode;
                return true;
            }else{
                next = next->right;
            }
        }else{
            break;
        }
    }
    return false;
}

BST的删除:

删除节点比较复杂,分为三种情况:

节点的左右节点都为空:

直接删除即可,使父节点指向NULL

节点的左右节点有一个为空:

直接删除即可,使父节点指向节点不为空的那个节点

节点的左右节点都不为空:

找到中序遍历顺序下该节点的下一节点,用该节点来替代这个节点的位置,同时要注意好替代前后的树的结构的保持,建议画图辅助理解

bool BST::BSTdelete(TreeNode* node , int val){
    TreeNode* pre = new TreeNode(INT_MIN);
    pre->left = node;
    TreeNode* record = pre; // 使用record来记录,使record->left指向root,来简化删除root节点的问题
    TreeNode* cur = node;
    while(cur){
        if(cur->val == val){
            TreeNode* curL = cur->left;
            TreeNode* curR = cur->right;
            bool isleft = (pre->left==cur);
            if(!curL&&!curR){// 叶子节点的情况
                if(isleft){
                    pre->left = nullptr;
                }else{
                    pre->right = nullptr;
                }
            }
            if(!curL){ //只有右子树的情况
                if(isleft){
                    pre->left = cur->right;
                }else{
                    pre->right = cur->right;
                }
                delete cur;
            }
            if(!curR){ // 只有左子树的情况
                if(isleft){
                    pre->left = cur->left;
                }else{
                    pre->right = cur->left;
                }
                delete cur;
            }
            //左右子树都有的情况
            TreeNode* next = curR;
            while(next->left){
                cur=next;
                next=next->left;
            }
            if(next==curR){//CUrR没有左节点的情况
                if(isleft){
                    pre->left = next;
                }else{
                    pre->right = next;
                }
                curR->left = curL;
                delete cur;
            }else{//curR有左节点的情况
                if(isleft){
                    pre->left = next;
                }else{
                    pre->right = next;
                }
                next->left = curL;
                cur->left = next->right;
                next->right = curR;
            }
            root = record->left;
            delete pre;
            return true;
        }else if(cur->val<val){
            pre=cur;
            cur=cur->right;
        }else{
            pre=cur;
            cur=cur->left;
        }
    }
    return false;
}

代码实现以及输出结果:

#include<bits/stdc++.h>
using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr){}
    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

class BST{
private:

    TreeNode* root;

    TreeNode* BSTsearch(TreeNode* node, int val);

    bool BSTinsert(TreeNode* node ,int val);

    void midorder(TreeNode* node){
        if(node){
            midorder(node->left);
            cout<<node->val<<" ";
            midorder(node->right);
        }
    }
    void preorder(TreeNode* node){
        if(node){
            cout<<node->val<<" ";
            preorder(node->left);
            preorder(node->right);
        }
    }

    bool BSTdelete(TreeNode* node, int val);
public:

    BST():root(nullptr){};
    BST(const TreeNode &rhs) : root(nullptr){};

    void Create(string input){
        //getline(cin,input);
        istringstream is(input);
        string ans;
        while(is>>ans){
            int val = atoi(ans.c_str());
            if(root==nullptr){
                root=new TreeNode(val);
            }else{
                BSTinsert(root,val);
            }
        }
    }
    void Search(int val){
        if(BSTsearch(this->root,val)!=nullptr){
            cout<<"success"<<endl;
        }else{
            cout<<"fail"<<endl;
        }
    }
    void Insert(int val){
        if(BSTinsert(root,val)){
            cout<< "insert "<<val <<" success"<<endl;
        }else{
            cout<<"fail"<<endl;
        }
    }
    void Delete(int val){
        if(BSTdelete(root,val)){
            cout<<"success"<<endl;
        }else{
            cout<<"fail"<<endl;
        }
    }
    void midvisit(){
        midorder(root);
        cout<<endl;
    }

    void previsit(){
        preorder(root);
        cout<<endl;
    }

};

TreeNode* BST::BSTsearch(TreeNode* node , int val){
    if(!node){return nullptr;}
    if(node->val == val){
        return node;
    }
    return node->val >val ? BSTsearch(node->left, val) : BSTsearch(node->right, val);
}

bool BST::BSTinsert(TreeNode* node , int val){
    TreeNode* next = node;
    TreeNode* newnode =new TreeNode(val);
    while(next){
        if(val<next->val){
            if(!next->left){
                next->left = newnode;
                return true;
            }else{
                next = next->left;
            }
        }else if(val>next->val){
            if(!next->right){
                next->right = newnode;
                return true;
            }else{
                next = next->right;
            }
        }else{
            break;
        }
    }
    return false;
}

bool BST::BSTdelete(TreeNode* node , int val){
    TreeNode* pre = new TreeNode(INT_MIN);
    pre->left = node;
    TreeNode* record = pre;
    TreeNode* cur = node;
    while(cur){
        if(cur->val == val){
            TreeNode* curL = cur->left;
            TreeNode* curR = cur->right;
            bool isleft = (pre->left==cur);
            if(!curL&&!curR){// 叶子节点的情况
                if(isleft){
                    pre->left = nullptr;
                }else{
                    pre->right = nullptr;
                }
            }

            if(!curL){ //只有右子树的情况
                if(isleft){
                    pre->left = cur->right;
                }else{
                    pre->right = cur->right;
                }
                delete cur;
            }

            if(!curR){ // 只有左子树的情况
                if(isleft){
                    pre->left = cur->left;
                }else{
                    pre->right = cur->left;
                }
                delete cur;
            }
            //左右子树都有的情况
            TreeNode* next = curR;
            while(next->left){
                cur=next;
                next=next->left;
            }
            if(next==curR){
                if(isleft){
                    pre->left = next;
                }else{
                    pre->right = next;
                }
                curR->left = curL;
                delete cur;
            }else{
                if(isleft){
                    pre->left = next;
                }else{
                    pre->right = next;
                }

                next->left = curL;
                cur->left = next->right;
                next->right = curR;
            }
            root = record->left;
            return true;

        }else if(cur->val<val){
            pre=cur;
            cur=cur->right;
        }else{
            pre=cur;
            cur=cur->left;
        }
    }
    return false;
}
int main(){
    BST test;
    test.Create("12 16 9 18 7 10 13 1 2 8 6");
    test.midvisit();
    test.previsit();
    test.Insert(11);
    test.midvisit();
    test.previsit();
    test.Delete(12);
    test.midvisit();
    test.previsit();
}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值