二叉搜索树

来源:互联网 发布:赵丽颖电影知乎 编辑:程序博客网 时间:2024/06/05 18:48

说起二叉搜索树,那么到底怎样的树才是二叉搜索树呢?
下面我们来看看:

它或者是一棵空树,或者是具有下列性质的二叉树:
1)若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
2)若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
3)它的左、右子树也分别为二叉排序树。

在创建树之前先创建结点:
这里使用键值对:

template<class K, class V>struct BinarySearchTreeNode{    BinarySearchTreeNode(const K& key, const V& value)        : _pLeft(NULL)        , _pRight(NULL)        , _key(key)        , _value(value)    {}    BinarySearchTreeNode<K, V>* _pLeft;    BinarySearchTreeNode<K, V>* _pRight;    K _key;    V _value;};

非递归算法寻找值为key的结点

    bool Find_Nor(const K& key)    {        Node* pCur = _pRoot;        while(pCur)        {            if(pCur->_key == key)                return true;            else if(key < pCur->_key)                pCur = pCur->_pLeft;            else                pCur = pCur->_pRight;        }        return false;    }

递归算法寻找值为key的结点

        bool _Find(Node* pRoot, const K& key)        {            if(pRoot)            {                if(key == pRoot->_key)                    return true;                else if(key < pRoot->_key)                    return _Find(_pRoot->_pLeft, key);                else                    return _Find(pRoot->_pRight, key);            }            return false;        }

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

非递归在树中插入一个新结点

    bool Insert(const K& key, const V& value)    {        if(NULL == _pRoot)        {            _pRoot = new Node(key, value);            return true;        }        // 找插入位置        Node* pCur = _pRoot;        Node* pParent = pCur;        while(pCur)        {            if(key < pCur->_key)            {                pCur = pCur->_pLeft;            }            else if(key > pCur->_key)            {                pCur = pCur->_pRight;            }            else                return false;        }        pCur = new Node(key, value);        if(key < pParent->_key)            pParent->_pLeft = pCur;        else            pParent->_pRight = pCur;        return true;    }

递归在树中插入一个新结点

        bool _Insert(Node* &pRoot, const K& key, const V& value)        {            if(NULL == pRoot)            {                pRoot = new Node(key, value);                return true;            }            else            {                if(key < pRoot->_key)                    return _Insert(pRoot->_pLeft, key, value);                else if(key > pRoot->_key)                    return _Insert(pRoot->_pRight, key, value);                else                    return false;            }        }

删除结点分很多情况:
首先查找元素是否在二叉搜索树中,如果不存在,则返回;否则要删除的结点可能分下面四种 情况:
1、要删除的结点无孩子结点;
2、要删除的结点只有左孩子结点;
3、要删除的结点只有右孩子结点;
4、要删除的结点有左、右孩子结点;
情况1可以归类到2或者3 对于上述情况,相应的删除方法如下:
a、直接删除该结点
b、删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点;
c、删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点;
d、在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点中,在来处理该结点的删除问题

在此我分别用了两种方法实现:
非递归删除某个结点

bool Remove(const K& key){    if(NULL == _pRoot)      return false;     // 删除的结点刚好是根,并且树中只有一个根节点    if(NULL == _pRoot->_pLeft && NULL == _pRoot->_pRight &&key == _pRoot->_key)    {        delete _pRoot;        _pRoot = NULL;        return true;    }    // 找到删除的结点    Node* pCur = _pRoot;    Node* pParent = NULL;    while(pCur)    {          if(key < pCur->_key)        {            pParent = pCur;            pCur = pCur->_pLeft;        }        else if(key > pCur->_key)        {            pParent = pCur;            pCur = pCur->_pRight;        }        else            break;    }    Node* pCur=_pRoot;    pCur=Find(key);    // pCur为要删除的结点    if(pCur)    {    // 删除结点只有右子树      if(NULL == pCur->_pLeft)        {            if(pCur != _pRoot)            {                if(pParent->_pLeft == pCur)                    pParent->_pLeft = pCur->_pRight;                else                    pParent->_pRight = pCur->_pRight;            }            else                _pRoot = pCur->_pRight;        }      else if(NULL == pCur->_pRight)   // 删除节点只有左子树      {            if(pCur != _pRoot)            {                if(pCur == pParent->_pLeft)                    pParent->_pLeft = pCur->_pLeft;                else                    pParent->_pRight = pCur->_pLeft;            }            else                _pRoot = pCur->_pLeft;        }        else    // 删除节点的左右子树都存在        {           Node* firstInOrder = pCur->_pRight;            while(firstInOrder->_pLeft)            {                pParent = firstInOrder;                firstInOrder = firstInOrder->_pLeft;            }            pCur->_key = firstInOrder->_key;            pCur->_value = firstInOrder->_value;            // firstInOrder右子树有可能为NULL            if(pParent->_pLeft == firstInOrder)                pParent->_pLeft = firstInOrder->_pRight;            else                pParent->_pRight = firstInOrder->_pRight;            pCur = firstInOrder;        }        delete pCur;        return true;    }   // 没有找到该节点return false;}

递归操作删除树中某个结点:

        bool _Remove(Node*& pRoot, const K& key)        {            if(pRoot)            {                if(key < pRoot->_key)                    return _Remove(pRoot->_pLeft, key);                else if(key > pRoot->_key)                    return _Remove(pRoot->_pRight, key);                else                {                    // 删除节点已经找到                    if(NULL == pRoot->_pLeft)                    {                        Node* pDel = pRoot;                        delete pDel;                        pRoot = pRoot->_pRight;                        return true;                    }                    else if(NULL == pRoot->_pRight)                    {                        Node* pDel = pRoot;                        delete pDel;                        pRoot = pRoot->_pLeft;                        return true;                    }                    else                    {                        Node* firstInOrder = pRoot->_pRight;                        while(firstInOrder->_pLeft)                            firstInOrder = firstInOrder->_pLeft;                        pRoot->_key = firstInOrder->_key;                        pRoot->_value = firstInOrder->_value;                        return _Remove(firstInOrder, firstInOrder->_key);                    }                }            }        }
原创粉丝点击