二叉检索树的C++实现

二叉检索树

  • 属性:对于二叉检索树(Binary Search Tree,BST)的任何一个结点,设其值为K,则该结点左子树中任意一个结点的值都小于K;该结点右字数中任意一个结点的值都大于或等于K。
  • 特点:按照中序遍历将各结点打印出来,就会得到由小到大排列的结点。
    如下图所示:图片描述图片描述
  • 在实现BST之前,首先需要对字典进行定义,字典提供在数据库中存储、查询、删除记录的功能。
    字典的ADT:
template<typename Key, typename E>
class Dictionary{
private:
    void operator =(const Dictionary&){}
    Dictionary(const Dictionary&){}
public:
    Dictionary(){}
    virtual ~Dictionary(){}
    virtual void clear() = 0;
    virtual void insert(const Key& k, const E& e) = 0;
    virtual E remove(const Key& k) = 0;
    virtual E removeAny() = 0;
    virtual E find(const Key& k) const  = 0;
    virtual int size() = 0;
};
  • BST的实现:
template<typename Key, typename E>
class BST : public Dictionary < Key, E > {
private:
    BSTNode<Key, E>* root;
    int nodecount;

    void clearhelp(BSTNode<Key, E>*);     //清除二叉树
    BSTNode<Key, E>* inserthelp(BSTNode<Key, E>*, const Key&, const E&); //插入函数
    BSTNode<Key, E>* deletemin(BSTNode<Key, E>*);                        //删除最小结点
    BSTNode<Key, E>* getmin(BSTNode<Key, E>*);                           //获取最小结点的值
    BSTNode<Key, E>* removehelp(BSTNode<Key, E>*, const Key&);  //移除函数
    E findhelp(BSTNode<Key, E>*, const Key&) const;     //查找函数
    void printhelp(BSTNode<Key, E>*, int) const;        //打印函数
    public:
    BST()  { root = NULL; nodecount = 0; }      //构造函数
    ~BST() { clearhelp(root); }                    //析构函数

    //清除二叉树
    void clear()
    {
        clearhelp(root);
        root = NULL;
        nodecount = 0;
    }
    //插入函数
    void insert(const Key& k,const E& e)
    {
        root = inserthelp(root, k, e);
        nodecount++;
    }
    //移除函数
    E remove(const Key& k)
    {
        E temp = findhelp(root, k);
        if (temp != NULL)
        {
            root = removehelp(root, k);
            nodecount--;
        }
        return temp;

    }
    //移除所有元素
    E removeAny()
    {
        if (root != NULL)
        {
            E temp = root->element;
            root = removehelp(root, root->key());
            nodecount--;
            return temp;
        }
        else return NULL;
    }
    //查找元素
    E find(const Key& k) const 
    {
        return findhelp(root, k);
    }
    //返回当前结点的数量
    int size() { return nodecount; }
    //打印二叉树
    void print() const
    {
        if (root == NULL)  cout << "The BST is empty!" << endl;
        else printhelp(root, 0);
    }
  • 查找函数:将字数的根结点及检索的值作为参数,使用递归函数实现。
template<typename Key, typename E>
E BST<Key, E>::findhelp(BSTNode<Key, E>* root, const Key& k) const
{
    if (root == NULL) return NULL;
    if (k < root->key())
        return findhelp(root->left(), k);//查找左边
    else if (k > root->key())
        return findhelp(root->right(), k);//查找右边
    else return root->element();          //找到了
}
  • 插入函数:要插入一个值K,首先必须要找到它应该放在书机构的什么地方。这样就会把它带到一个叶结点,或者一个在待插入的方向上没有子结点的分支结点。将这个结点即为R,接着,把一个包含K的结点作为R的子结点加上去。
    从根结点到被插入结点的父节点,该路径上的各个结点都被赋予了相应的子结点指针值。
template<typename Key, typename E>
BSTNode<Key, E>* BST<Key, E>::inserthelp(BSTNode<Key, E>* root, const Key& k, const E& it)
{
    if (root == NULL)    //如果为空,则建立一个结点
        return new BSTNode<Key, E>(k, it, NULL, NULL);
    if (k < root->key())
        root->setLeft(inserthelp(root->left(), k, it));
    else 
        root->setRight(inserthelp(root->right(), k, it));
    return root;           //返回被插入结点
}
  • 由于函数调用了deletemin的缘故,在回到根结点路径上的各个结点的左指针都被重新赋予指向子树。
template<typename Key, typename E>
BSTNode<Key, E>* BST<Key, E>::deletemin(BSTNode<Key, E>* rt)
{
    if (rt->left() == NULL)
    {
        BSTNode<Key, E>* temp = rt->right();
        delete rt;
        return temp->right();
    }

    else{
        rt->setLeft(deletemin(rt->left()));
        return rt;
    }
}
  • 返回二叉树的最小元素的结点
template<typename Key, typename E>
BSTNode<Key, E>* BST<Key, E>::getmin(BSTNode<Key, E>* rt)
{
    if (rt->left() == NULL)
        return rt;
    else return getmin(rt->left());
}
  • 如果想把一个有两个子结点的结点值删除,只需要对其右字数调用函数deletemin,并用寒素的返回值替代被删除的值。
template<typename Key, typename E>
BSTNode<Key, E>* BST<Key, E>::removehelp(BSTNode<Key, E>* rt, const Key& k)
{
    if (rt == NULL)        //k不在树里
        return NULL;
    //查找所要删除的结点
    else if (k < rt->key())      
        rt->setLeft(removehelp(rt->left(), k));     
    else if (k > rt->key())
        rt->setRight(removehelp(rt->right(), k));
    //找到了,删除
    else
    {
        BSTNode<Key, E>* temp = rt;
        //只有右子结点
        if (rt->left() == NULL)
        {
            rt = rt->right();
            delete temp;
        }
        //只有左子结点
        else if (rt->right() == NULL)
        {
            rt = rt->left();
            delete temp;
        }
        //有两个结点
        else
        {
            BSTNode<Key, E>* t = getmin(rt->right());
            rt->setElement(t->element());
            rt->setKey(t->key());
            rt->setRight(deletemin(rt->right()));
            delete temp;
        }
    }
    return rt;
}
  • 采用后序遍历进行释放
template<typename Key, typename E>
void BST<Key, E>::clearhelp(BSTNode<Key, E>* root)
{
    if (root == NULL)
        return;
    clearhelp(root->left());
    clearhelp(root->right());
    delete root;
}
  • 用中序遍历将BST打印出来
template<typename Key, typename E>
void BST<Key, E>::printhelp(BSTNode<Key, E>* root, int level) const
{
    if (root == NULL) return;      //空树
    printhelp(root->left(), level + 1);   //打印左子树
    for (int i = 0; i < level; i++)
        cout << " ";
    cout << root->key() << endl;       //打印结点值
    printhelp(root->right(), level + 1);    //打印右子树
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值