二叉搜索树

二叉搜索树
【概念】
二叉搜索树:又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树
1、若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
2、若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
3、它的左右子树也分别为二叉搜索树
例:此树就是一颗二叉搜索树。
这里写图片描述
【操作】

—搜索:若根节点不为空
如果根节点的key==查找key,返回true
如果根节点的key<查找key,在其左子树中查找
如果根节点的key>查找key,在其右子树中查找
否则,返回false

—插入:
在向二叉搜索树中插入新元素时,必须先检测这个元素是否在树中已经存在。如果搜索成功,说明该元素已经存在,则不进行插入;否则将新元素加入到搜索停止的地方。

—删除:
首先查找元素是否在二叉搜索树中,如果不存在,则返回;否则要删除的结点可能分下面四种情况:

1、要删除的结点无孩子结点;
2、要删除的结点只有左孩子结点;
3、要删除的结点只有右孩子结点;
4、要删除的结点有左、右孩子结点;

对于上述情况,相应的删除方法如下:
a、直接删除该结点
b、删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子点;
c、删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子点;
d、在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值补 到被删除节点中,在来处理该结点的删除问题

1–>a :这里写图片描述
2–b :这里写图片描述
3–c :这里写图片描述
4–d :这里写图片描述

源代码:

template<class T>
struct BinarySearchTreeNode
{
    BinarySearchTreeNode<T>*_pleft;
    BinarySearchTreeNode<T>*_pright;
    T _key;
    BinarySearchTreeNode(const T&key)
        :_pleft(NULL)
        , _pright(NULL)
        , _key(key)
    {}
};

template<class T>
class BinarySearchTree
{
    typedef BinarySearchTreeNode<T> Node;
public:
    BinarySearchTree()
        :_proot(NULL)
    {}
    BinarySearchTree(T*a, size_t size)
    {
        _proot = NULL;
        for (int i = 0; i < size; ++i)
        {
            Insert(a[i]);
        }
    }
    bool Insert(const T&data)
    {
        if (_proot == NULL)
        {
            _proot = new Node(data);
            return true;
        }
        Node*pCur = _proot;
        Node*parent = NULL;
        while (pCur)
        {
            parent = pCur;
            if (pCur->_key < data)
                pCur = pCur->_pright;
            else if (pCur->_key>data)
                pCur = pCur->_pleft;
            else
                return false;
        }
        if (parent->_key < data)
            parent->_pright = new Node(data);
        else if(parent->_key > data)
            parent->_pleft = new Node(data);
        return true;
    }

    Node* Find(const T&data)
    {
        Node*pCur = _proot;
        while (pCur)
        {
            if (data == pCur->_key)
                return pCur;
            if (data < pCur->_key)
                pCur = pCur->_pleft;
            else
                pCur = pCur->_pright;
        }
        return NULL;
    }

    bool Remove(const T&data)
    {
        Node*pCur = _proot;
        Node*parent = NULL;
        while (pCur)
        {
            if (pCur->_key < data)
            {
                parent = pCur;
                pCur = pCur->_pright;
            }
            else if (pCur->_key>data)
            {
                parent = pCur;
                pCur = pCur->_pleft;
            }
            else
            {
                if (pCur->_pleft == NULL)//当前节点左孩子为空,将右孩子直接复制
                {
                    if (parent == NULL)//判断当前节点是不是根节点
                    {
                        _proot = pCur->_pright;
                    }
                    else//待删除结点为右孩子
                    {
                        if (parent->_pleft == pCur)
                            parent->_pleft = pCur->_pright;
                        else
                            parent->_pright = pCur->_pright;
                    }
                    delete pCur;
                }
                else if (parent->_pright == NULL)//待删除结点为左孩子
                {
                    if (parent == NULL)
                    {
                        _proot = pCur->_pright;
                    }
                    else
                    {
                        if (parent->_pleft == pCur)
                            parent->_pleft = pCur->_pleft;
                        else
                            parent->_pright = pCur->_pleft;
                    }
                    delete pCur;
                }


                else//左右子树都不为空,将右子树中最左节点交换
                {
                    Node*tmp = pCur->_pright;
                    Node*prev = pCur;
                    while (tmp->_pleft)
                    {
                        prev = tmp;
                        tmp = tmp->_pleft;
                    }
                    swap(tmp->_key, pCur->_key);
                    if (tmp==prev->_pright)
                    {
                        pCur->_pright = tmp->_pright;
                    }
                    else if (prev->_pleft==tmp)
                    {
                        prev->_pleft = tmp->_pright;
                    }
                    delete tmp;
                }
                return true;
            }
        }
        return false;
    }


    BinarySearchTree<T>& operator=(BinarySearchTree<T>&tree)
    {
        if (this != &tree)
        {
            BinarySearchTree<T>tmp(tree);
            swap(_proot, tmp._proot);
        }
        return *this;
    }

    BinarySearchTree(const BinarySearchTree<T>&tree)
        :_proot(NULL)
    {
        if (tree._proot == NULL)
            return;
        queue<Node*>q;
        q.push(tree._proot);
        while (!q.empty())
        {
            Node*pCur = q.front();
            Insert(pCur->_key);
            q.pop();
            if (pCur->_pleft)
            {
                q.push(pCur->_pleft);
            }
            if (pCur->_pright)
            {
                q.push(pCur->_pright);
            }
        }
    }

    ~BinarySearchTree()
    {
        _Destory(_proot);
    }

    Node*_Find_Min(const Node&proot)
    {
        assert(proot);
        while (proot->_pleft)
        {   
            proot = proot->_pleft;
        }
        return proot;
    }

    Node*_Find_MAX(const Node&proot)
    {
        assert(proot);
        while (proot->_pright)
        {
            proot = proot->_pright;
        }
        return proot;
    }



private:
    void _Destory(Node*proot)
    {
        if (proot == NULL)
            return;
        _Destory(proot->_pleft);
        _Destory(proot->_pright);
        delete proot;
    }
private:
    BinarySearchTreeNode<T>*_proot;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值