红黑树基本操作实现

来源:互联网 发布:表情呆滞面部僵硬知乎 编辑:程序博客网 时间:2024/06/06 03:15

红黑树的插入,删除简单实现

主要理解的难点在删除的实现,当删除节点存在左右子节点时,需选择右侧后续节点,然后替换两个节点,当被替换节点是叶节点时,需要重新平衡该树,此时以空节点染黑代替进行平衡操作,再做各种变换,与书上的图操作相似, 详见“[balance]”

#ifndef CRBTREE_H#define CRBTREE_H#include <cstddef>using namespace std;enum NodeColor{    colorred,    colorblack};template <class T>struct RBNode{    NodeColor color;    RBNode *leftnode;    RBNode *rightnode;    RBNode *parentnode;    T obj;};template <class T>RBNode<T> *__InitNode(const T& obj){    RBNode<T> *rbnode = new RBNode<T>();    rbnode->color = colorred;    rbnode->leftnode = NULL;    rbnode->rightnode = NULL;    rbnode->parentnode = NULL;    rbnode->obj = obj;    return rbnode;}template <class T>class CRBTree{public:    typedef RBNode<T> NodeType;    typedef NodeType* NodeTypePtr;    typedef T value_type;    CRBTree(){        headnode = NULL;    }    ~CRBTree(){    }    bool Empty() { return headnode == NULL; }    void Insert(const value_type &obj)    {        NodeType *newnode = __InitNode(obj);        if (Empty())        {            newnode->color = colorblack;            headnode = newnode;        }        else        {            _InsertNode(newnode);            if (newnode->parentnode->color == colorred)            {                _Recolor(newnode);            }        }    }    void Erase(const value_type &obj)    {        NodeType *_EraseNode = _FindNode(headnode, obj);        if (_EraseNode)        {            NodeTypePtr _Fixnode;// the node to recolor as needed            NodeTypePtr _Fixnodeparent;// parent of _Fixnode (which may be nil)            NodeTypePtr _Pnode = _EraseNode;            if (_Pnode->leftnode == NULL)                _Fixnode = _Pnode->rightnode;// stitch up right subtree            else if (_Pnode->rightnode == NULL)                _Fixnode = _Pnode->leftnode;// stitch up left subtree            else            {// two subtrees, must lift successor node to replace erased                _Pnode = (++iter(_EraseNode)).data();// _Pnode is successor node                _Fixnode = _Pnode->rightnode;// _Fixnode is only subtree            }            if (_Pnode == _EraseNode)            {   // at most one subtree, relink it,only black parent link one red child                _Fixnodeparent = _EraseNode->parentnode;                if (_Fixnode != NULL)                    _Fixnode->parentnode = _Fixnodeparent;                if (headnode == _EraseNode)                    headnode = _Fixnode;                else if (_Fixnodeparent->leftnode == _EraseNode)                    _Fixnodeparent->leftnode = _Fixnode;                else                    _Fixnodeparent->rightnode = _Fixnode;            }            else            {  //two subtrees, find the successor node and swap with the Erasenode                _EraseNode->leftnode->parentnode = _Pnode;                _Pnode->leftnode = _EraseNode->leftnode;                if (_EraseNode->rightnode == _Pnode)                {                    _Fixnodeparent = _Pnode;                }                else                {                    _Fixnodeparent = _Pnode->parentnode;                    if (_Fixnode != NULL)                        _Fixnode->parentnode = _Fixnodeparent;                    _Fixnodeparent->leftnode = _Fixnode;                    _Pnode->rightnode = _EraseNode->rightnode;                    _EraseNode->rightnode->parentnode = _Pnode;                }                if (headnode == _EraseNode)                    headnode = _Pnode;                else if (_EraseNode->parentnode->leftnode == _EraseNode)                    _EraseNode->parentnode->leftnode = _Pnode;                else                    _EraseNode->parentnode->rightnode = _Pnode;                _Pnode->parentnode = _EraseNode->parentnode;                //swap color                NodeColor color = _Pnode->color;                _Pnode->color = _EraseNode->color;                _EraseNode->color = color;            }            if (_EraseNode->color == colorblack)            {                if (_Fixnode != NULL)                    _Fixnode->color = colorblack;                else                {   //[balance]                    while (_Fixnode != headnode && (_Fixnode == NULL || _Fixnode->color == colorblack))                    {                        if (_Fixnode == _Fixnodeparent->leftnode)                        {                            NodeTypePtr _Unclenode = _Fixnodeparent->rightnode;                            if (_Unclenode->color == colorred)                            {                                _Unclenode->color = colorblack;                                _Fixnodeparent->color = colorred;                                _LeftRotate(_Fixnodeparent);                                _Unclenode = _Fixnodeparent->rightnode;                            }                            if ((_Unclenode->leftnode == NULL || _Unclenode->leftnode->color == colorblack) &&                                    (_Unclenode->rightnode == NULL || _Unclenode->rightnode->color == colorblack))                            {                                _Unclenode->color = colorred;                                _Fixnode = _Fixnodeparent;                                _Fixnodeparent = _Fixnodeparent->parentnode;                            }                            else                            {                                if (_Unclenode->rightnode == 0 || _Unclenode->rightnode->color == colorblack)                                {                                    if (_Unclenode->leftnode != NULL)                                        _Unclenode->leftnode->color = colorblack;                                    _Unclenode->color = colorred;                                    _RightRotate(_Unclenode);                                    _Unclenode = _Fixnodeparent->rightnode;                                }                                _Unclenode->color = _Fixnodeparent->color;                                _Fixnodeparent->color = colorblack;                                if (_Unclenode->rightnode != NULL) _Unclenode->rightnode->color = colorblack;                                _LeftRotate(_Fixnodeparent);                                break;                            }                        }                        else                        {                            NodeTypePtr _UncleNode = _Fixnodeparent->leftnode;                            if (_UncleNode->color == colorred)                            {                                _UncleNode->color = colorblack;                                _Fixnodeparent->color = colorred;                                _RightRotate(_Fixnodeparent);                                _UncleNode = _Fixnodeparent->leftnode;                            }                            if ((_UncleNode->rightnode == NULL ||_UncleNode->rightnode->color == colorblack) &&                                (_UncleNode->leftnode == NULL || _UncleNode->leftnode->color == colorblack))                            {                                _UncleNode->color = colorred;                                _Fixnode = _Fixnodeparent;                                _Fixnodeparent = _Fixnodeparent->parentnode;                            }                            else                            {                                if (_UncleNode->leftnode == NULL || _UncleNode->leftnode->color == colorblack)                                {                                    if (_UncleNode->rightnode)                                        _UncleNode->rightnode->color = colorblack;                                    _UncleNode->color = colorred;                                    _LeftRotate(_UncleNode);                                    _UncleNode = _Fixnodeparent->leftnode;                                }                                _UncleNode->color = _Fixnodeparent->color;                                _Fixnodeparent->color = colorblack;                                if (_UncleNode->leftnode) _UncleNode->leftnode->color = colorblack;                                _RightRotate(_Fixnodeparent);                                break;                            }                        }                    }                    if (_Fixnode) _Fixnode->color = colorblack;                }            }            delete _EraseNode;        }    }    class iter{    public:        iter(NodeType *node)            :_node(node)        {        }        iter operator ++()        {            if (_node->rightnode)            {                _node = _node->rightnode;                while(_node && _node->leftnode)                {                    _node = _node->leftnode;                }            }            else if (_node->parentnode == NULL)            {                _node = NULL;            }            else if (_node == _node->parentnode->leftnode)            {                _node = _node->parentnode;            }            else if (_node == _node->parentnode->rightnode)            {                NodeType *_parent = _node->parentnode;                if (_parent->parentnode && _parent == _parent->parentnode->leftnode)                {                    _node = _parent->parentnode;                }                else                {                    _node = NULL;                }            }            return *this;        }        bool operator == (const iter& other)        {            return _node == other._node;        }        bool operator != (const iter& other)        {            return _node != other._node;        }        NodeType* operator -> () const { return _node;}        NodeType* data() const { return _node; }    private:        NodeType *_node;    };    iter begin()    {        NodeType *_tnode = headnode;        if (_tnode != NULL)        {            while(_tnode->leftnode)            {                _tnode = _tnode->leftnode;            }        }        return iter(_tnode);    }    iter end()    {        return iter(NULL);    }    void clear()    {        _Erase(headnode);        headnode = NULL;    }private:    NodeType *headnode;    void _LeftRotate(NodeType *nodeA){        NodeType *nodeB = nodeA->rightnode;        NodeType *nodeC = nodeB->leftnode;        nodeA->rightnode = nodeC;        if (nodeC) nodeC->parentnode = nodeA;        nodeB->leftnode = nodeA;        nodeB->parentnode = nodeA->parentnode;        if (nodeA->parentnode == NULL)            headnode = nodeB;        else        {            if (nodeA->parentnode->leftnode == nodeA)                nodeA->parentnode->leftnode = nodeB;            else                nodeA->parentnode->rightnode = nodeB;        }        nodeA->parentnode = nodeB;    }    void _RightRotate(NodeType *nodeA){        NodeType *nodeB = nodeA->leftnode;        NodeType *nodeC = nodeB->rightnode;        nodeA->leftnode = nodeC;        if (nodeC) nodeC->parentnode = nodeA;        nodeB->rightnode = nodeA;        nodeB->parentnode = nodeA->parentnode;        if (nodeA->parentnode == NULL)            headnode = nodeB;        else        {            if (nodeA->parentnode->leftnode == nodeA)                nodeA->parentnode->leftnode = nodeB;            else                nodeA->parentnode->rightnode = nodeB;        }        nodeA->parentnode = nodeB;    }    void _InsertNode(NodeType *node)    {        NodeType *parent = headnode;        do{            if (node->obj < parent->obj)            {                if (parent->leftnode == NULL)                {                    parent->leftnode = node;                    node->parentnode = parent;                    break;                }                else                    parent = parent->leftnode;            }            else            {                if (parent->rightnode == NULL)                {                    parent->rightnode = node;                    node->parentnode = parent;                    break;                }                else                    parent = parent->rightnode;            }        }while(1);    }    NodeType* _FindNode(NodeType *pNode,const value_type& obj)    {        NodeType *_node = pNode;        do{            if (_node == NULL || _node->obj == obj)            {                return _node;            }            else if (_node->obj < obj)            {                return _FindNode(_node->rightnode, obj);            }            else            {                return _FindNode(_node->leftnode, obj);            }        }while(1);    }    void _Recolor(NodeType *node)    {        NodeType *_parent = node->parentnode;        if (node == headnode)        {            node->color = colorblack;        }        else if (_parent->color == colorblack)        {            return;        }        else        {            NodeType *_grand = _parent->parentnode;            if (_parent == _grand->leftnode)            {                NodeType *_uncle = _grand->rightnode;                if (_uncle && _uncle->color == colorred)                {                    _parent->color = colorblack;                    _uncle->color = colorblack;                    _grand->color = colorred;                    _Recolor(_grand);                }                else                {                    if (node == _parent->rightnode)                    {                        node = node->parentnode;                        _LeftRotate(node);                    }                    node->parentnode->color = colorblack;                    node->parentnode->parentnode->color = colorred;                    _RightRotate(node->parentnode->parentnode);                }            }            else            {                NodeType *_uncle = _grand->leftnode;                if (_uncle && _uncle->color == colorred)                {                    _parent->color = colorblack;                    _uncle->color = colorblack;                    _grand->color = colorred;                    _Recolor(_grand);                }                else                {                    if (node == _parent->leftnode)                    {                        node = node->parentnode;                        _RightRotate(node);                    }                    node->parentnode->color = colorblack;                    node->parentnode->parentnode->color = colorred;                    _LeftRotate(node->parentnode->parentnode);                }            }        }    }    void _Erase(NodeType *node)    {        for (NodeType *_Pnode = node; _Pnode != NULL; node = _Pnode)        {// free subtrees, then node            _Erase(_Pnode->rightnode);            _Pnode = _Pnode->leftnode;            delete node;        }    }};#endif // CRBTREE_H

测试代码:

#include <iostream>#include "rbtree.h"using namespace std;void printtree(CRBTree<int>& rbtree){    //check tree balance    int blackdepth = 0;    for ( CRBTree<int>::iter it = rbtree.begin(); it != rbtree.end(); ++it)    {        int branchdepth = 0;        if (it->leftnode == NULL || it->rightnode == NULL)        {            branchdepth ++;            RBNode<int>* node = it.data();            while (node != NULL)            {                if (node->color == colorblack)                    branchdepth++;                node = node->parentnode;            }            if (blackdepth == 0)                blackdepth = branchdepth;            else if (blackdepth != branchdepth)                cout << "RBTree is not balance now!\n";        }    }    for ( CRBTree<int>::iter it = rbtree.begin(); it != rbtree.end(); ++it)    {        cout << it->obj;        const char *temp = (it->color==colorblack) ? "B" : "R";        cout << temp;        if (it->leftnode != NULL)            cout << 'l';        if (it->rightnode != NULL)            cout << 'r';        if (it->parentnode == NULL)            cout << 'H';        cout << "  ";    }    cout << endl;}int main(){    CRBTree<int> rbtree;    for (int i=0; i<61; i++)    {        rbtree.Insert(i);        printtree(rbtree);    }int arrint[] = {1, 7, 5, 20, 4, 6, 9, 10, 17, 3, 2, 15, 60, 55};    for (unsigned int i=sizeof(arrint)/sizeof(arrint[0]); i>0; i--)    {        rbtree.Erase(arrint[i-1]);        printtree(rbtree);    }rbtree.clear();    return 0;}



0 0
原创粉丝点击