二叉检索树的C++实现

来源:互联网 发布:vb安装win10 编辑:程序博客网 时间:2024/06/05 09:04

二叉检索树

  • 属性:对于二叉检索树(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;};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 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);    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 查找函数:将字数的根结点及检索的值作为参数,使用递归函数实现。
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();          //找到了}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 插入函数:要插入一个值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;           //返回被插入结点}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 由于函数调用了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;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 返回二叉树的最小元素的结点
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());}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 如果想把一个有两个子结点的结点值删除,只需要对其右字数调用函数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;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 采用后序遍历进行释放
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;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 用中序遍历将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);    //打印右子树}
原创粉丝点击