二叉搜索树(Binary Search Tree)的C++实现

二叉搜索树C++实现

需要具备的基础知识

  • C++基础(继承、多态、异常机制)

  • 结构体、类模板和函数模板

  • 二叉搜索树(Binary Search Tree)的概念

    • 左子树元素比树根小

    • 右子树元素比树根大

    • 左右子树都是二叉搜索树

  • 二叉搜索树的查找、插入和删除算法

需求分析

  • 查找

    • 查找最大值

    • 查找最小值

    • 查找某个值

  • 插入

  • 删除

    • 删除叶子

    • 删除单子节点

    • 删除双子节点

      • 用左子树最大或右子树最小元素代替待删节点

      • 删左子树最大或右子树最小

二叉搜索树的节点定义

二叉搜索树的节点和二叉树的节点定义一致,参见这篇文章二叉树C++实现

二叉树的定义

二叉树类已完成定义,参见二叉树C++实现。因此定义一个二叉搜索树的模板类,公有继承自二叉树类。

//
//定义一个二叉树的模板类
//
template<class Elem>
class BSTree : public BinTree<Elem>{
protected:
public:
    BSTree(){
        this->m_root = nullptr;
    }    
};

查找需求实现

递归实现查找最大值、查找最小值的功能。

  • 定义类内部受保护的成员函数rFindMax()、rFindMin()。
protected:
//
//递归查找最大值
//
    TreeNode<Elem>* rFindMax(TreeNode<Elem> *root) const{
        if (!root->right){
            return root;
        }
        return rFindMax(root->right);
    }
//
//递归查找最小值
//
    TreeNode<Elem>* rFindMin(TreeNode<Elem> *root) const{
        if (!root->left){
            return root;
        }
        return rFindMax(root->left);
    } 

迭代实现查找最大值、查找最小值和查找某个值的功能。

  • 定义用户API函数findMax()、findMin()、findElem(Elem val)。
//
//迭代查找最大值
//找到树根,在右边有节点,继续往右查找
//如果右边没有节点,就找到了最大值
//建议使用循环迭代。若用递归,返回值递归函数,尾递归效率比循环低
//
public:
    TreeNode<Elem>* findMax() const{
        if (this->m_root == nullptr){
            return nullptr;
        }
        TreeNode<Elem> *tmpNode = this->m_root;
        while (tmpNode->right){
            tmpNode = tmpNode->right;
        }
        return tmpNode;
    }
//
//迭代查找最小值
//找到树根,在左边有节点,继续往左查找
//如果左边没有节点,就找到了最大值
//
    TreeNode<Elem>* findMin() const{
        if (this->m_root == nullptr){
            return nullptr;
        }
        TreeNode<Elem> *tmpNode = this->m_root;
        while (tmpNode->left){
            tmpNode = tmpNode->left;
        }
        return tmpNode;
    }
//
//迭代查找目标值
//
    TreeNode<Elem>* findElem(Elem val) const{
        TreeNode<Elem> *tmpNode = this->m_root;
        while (tmpNode && val != tmpNode->data){
            if(val < tmpNode->data){
                tmpNode = tmpNode->left;
            }
            else{
                tmpNode = tmpNode->right;
            }
        }
        return tmpNode;
    }

插入需求实现

递归实现插入

  • 定义类内部受保护的成员函数rinsert(注:加上virtual修饰是为了后面写平衡二叉树的子类可以重写rinsert函数)
protected:
//
//递归插入
//
    virtual TreeNode<Elem>* rinsert(TreeNode<Elem> *root, Elem val){
        if (!root){
            root = new TreeNode<Elem>(val);
            if (!root){
                throw -1;
            }
        }
        else if(val < root->data){
            root->left = rinsert(root->left, val);
        }
        else if(val > root->data){
            root->right = rinsert(root->right, val);
        }
        else{
            throw -2;
        }
        return root;
    }
  • 定义用户API函数
//
//插入函数
//
public:
    bool insert(Elem val){
        try{
            this->m_root = rinsert(this->m_root, val);
            return true;
        }
        catch (int e){
            return false;
        }
        //return true;
    }

删除需求实现

递归实现删除功能,删除功能较为复杂,有如下三种场景:

  • 待删节点为叶子直接delete节点

  • 待删节点只有一个儿子节点的节点

  • 待删节点双子节点,用左子树最大或右子树最小元素代替待删节点,再删除左子树最大或右子树最小节点

定义类内部受保护的成员函数rErase

protected:
TreeNode<Elem>* rErase(TreeNode<Elem> *root, Elem val){
        TreeNode<Elem> *tmpNode;
        if (!root){
            throw -1;
        }
        else if(val < root->data){
            root->left = rErase(root->left, val);
        }
        else if (val > root->data){
            root->right = rErase(root->right, val);
        }
        else{
            if (root->left && root->right){
                tmpNode = rFindMax(root->left);
                root->data = tmpNode->data;//拷贝值
                root->left = rErase(root->left, tmpNode->data);//递归删除
            }
            else{
                tmpNode = root;
                root = root->left ? root->left : root->right;
                delete tmpNode;
            }
        }
        return root;
    }

定义用户API函数

public:
bool erase(Elem val){
        try{
            this->m_root = rErase(this->m_root, val);
            return true;
        }
        catch (int e){
            return false;
        }
    }

代码测试

int main(){
    BSTree<int> bst;
    bst.insert(10);
    bst.insert(5);
    bst.insert(20);
    bst.insert(8);
    bst.insert(15);
    bst.insert(2);
    bst.insert(6);
    bst.rPrint();//在基类中定义的函数可以在子类中使用
    cout << "----------------" << endl;
    bst.erase(10);
    bst.rPrint();
    cout << bst.findVal(15)->data << endl;
    cout << "最大值:" << bst.findMax()->data << endl;
    cout << "最小值:" << bst.findMin()->data << endl;
}

后续会介绍平衡二叉树,敬请期待。

完整的代码后面会上传到github供参考。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值