红黑树基本操作实现

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

主要理解的难点在删除的实现,当删除节点存在左右子节点时,需选择右侧后续节点,然后替换两个节点,当被替换节点是叶节点时,需要重新平衡该树,此时以空节点染黑代替进行平衡操作,再做各种变换,与书上的图操作相似, 详见“[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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值