您的位置:首页 > 编程语言

编程练习——红黑树(RedBlackTree)

2008-09-09 16:48 453 查看
   在网上搜索了很多红黑树的资源,发现自己看代码的能力还是有些欠缺。很多都看不懂,后来找到一篇英文红黑树文献,终于弄明白了红黑树的删除插入是怎么做的。但是那片文献好像还有些漏洞,其中有一种删除情况,他并没有考虑到。如果大家想看的话可以搜索下 "red-black trees" ,由 prof. Lyn Turbak所写。因为时间关系,插入算法只是实现了非CLR算法。删除算法我也不知道叫什么名字(文献里没有讲)。但是删除结果依旧符合红黑树。

  建立红黑树节点的时候,考虑到因为经常要和一个节点的父亲节点打交道,所以采用了在节点里添加父亲节点的指针的方法。这样即方便也提高效率。另外也好调试。如果一味采用递归..估计人会看疯掉的。插入的时候,采用的是先插入删除的时候红色节点,然后在判断是否违反红红条件。违反的话就左旋右旋进行调整。否则就插入成功。删除的时候先删除节点,这个过程和删除二叉查找树节点一致。删除时要看真正要删除的节点是否是根节点,是否是黑色节点。因为红色节点和根节点删除不会调整树形。如果删除的是黑色节点,那么要看替换他的节点(这里的替换一定是左子树树根,因为如果有右子树,那么被删除的也不会是这个节点,记住二叉查找树的删除过程)是否是黑色节点(这里如果左子树为空,那他也是黑色节点)。如果是黑色节点,那么一定要调整树的结构,否则就直接染色。调整树结构时要考虑的情况就非常多了。一共有9种情况需要考虑。

 

  下面是代码部分,删除时如何调整在代码注释中。至于insert操作,看看文献就应该会做了。

 

/*

* create RBNode class for construction RBTree

* create by chico chen

* date: 2008/09/04

* 如需转载注明出处

*/

template<class T>

#define RED 0

#define BLACK 1

class RBNode

{

public:

    T data;

    RBNode<T>* left;

    RBNode<T>* right;

    RBNode<T>* parent;

    int color;

    RBNode(T& data)

    {

        this->data = data;

        left = NULL;

        right = NULL;

        parent = NULL;

        color = RED; 

    }

    RBNode(T& data, RBNode<T>* left, RBNode<T>* right, RBNode<T>* parent)

    {

        this->data = data;

        this->left = left;

        this->right = right;

        this->parent = parent;

        color = RED;

    }

    ~RBNode()

    {

        this->left = this->right = this->parent = NULL;

        color = RED;

    }

};

 

 

下面是红黑树代码

 

/*

* this is red-black-tree code

* this code is not efficent in inserting

*

* create by chico chen

* date: 2008/09/04

* 如需转载注明出处

*/

#include "RBNode.h"

template<class T>

class RBTree

{

private:

    RBNode<T>* root;

public:

    RBTree()

    {

        this->root = NULL;

    }

    ~RBTree()

    {

        clearTree(this->root);

    }

    void print()

    {

        print(this->root,0);

    }

    

    void insert(T& data)

    {

        RBNode<T>* node = new RBNode<T>(data);

        insertNode(node);

    }

    void deleteKey(T& data)

    {

        deleteNode(data);

    }

    bool RBTreeTest()

    {

        try

        {

            getBlackNum(this->root);

        }

        catch(...)

        {

            return false;

        }

        return true;

    }

private:

    void print(RBNode<T>* subRoot, int num)

    {

        if(subRoot != NULL)

        {

            print(subRoot->right,num+3);

            for(int i = 0; i < num; i++)

            {

                cout << " ";

            }

            cout << subRoot->data<<"("<<subRoot->color<<")"<<endl;

            print(subRoot->left,num+3);

        }

    }

    void clearTree(RBNode<T>* subRoot)

    {

        if(subRoot == NULL)

            return;

        clearTree(subRoot->left);

        clearTree(subRoot->right);

        delete subRoot;

    }

    RBNode<T>* deleteMin(RBNode<T>* subRoot,RBNode<T>** parent)

    {

        

        while(subRoot != NULL)

        {

            parent = &subRoot;

            if(subRoot->right != NULL)

            {

                subRoot = subRoot->right;

            }

            else

            {

                break;

            }

        }

        return subRoot;

    }

    void deleteNode(T& data)

    {

        if(root == NULL)

        {

            throw "Empty tree";

        }

        RBNode<T>* subRoot = root;

        while(subRoot != NULL)

        {

            if(subRoot->data > data)

            {

                subRoot = subRoot->left;

            }

            else if(subRoot->data < data)

            {

                subRoot = subRoot->right;

            }

            else

            {

                // find the data

                // use the midOrder last one which is before the data node to replace

                RBNode<T>* inParent = subRoot;

                RBNode<T>* deleteNode = deleteMin(subRoot->left,&inParent);

                RBNode<T>* realDelete = NULL;

                if(deleteNode != NULL)

                {

                    subRoot->data = deleteNode->data; // copy

                    realDelete = deleteNode;

                    //real delete

                }

                else

                {

                    realDelete = subRoot;

                    //real delete

                }

                if(realDelete->parent == NULL)

                {

                    // delete root

                    delete realDelete;

                }

                else

                {

                    // nothing at realDelete->right

                    RBNode<T>* parent = realDelete->parent;

                    RBNode<T>* subATree = NULL;

                    if(parent->left == realDelete)

                    {

                        parent->left = realDelete->left;

                    }

                    else

                    {

                        parent->right = realDelete->left;

                    }

                    subATree = realDelete->left;

                    if(realDelete->left != NULL)

                    {

                        realDelete->left->parent = parent;

                    }

                    int color = realDelete->color;

                    delete realDelete;

                    if(color == BLACK && 

                        (subATree == NULL || subATree->color == BLACK))

                    {

                        

                        

                        deleteRebuild(subATree,parent);

                    }

                    else if(color == BLACK && subATree->color == RED)

                    {

                        subATree->color = BLACK;

                    }

                    else

                    {

                        // do nothing

                    }

                    break;

                }

            }

        }

    }

    /* delete them if you want

    *

    //     x(r)                c(r)

    //     /  /                /  /

    //   `a(b) b(b) -->     x(b)   b(b)

    //         /            /

    //        c(r)         a(b)

    // LRL means L-> double black is at left, and rotate is RL

    RBNode<T>* LRLCaseA(RBNode<T>* x)

    {

        RLRotate(x,x->right,x->right->left);

        x->color = BLACK;

        return x->parent;

        

    }

    //     x(r)                 b(r)

    //     /  /                 /  /

    //   `a(b) b(b)   -->    x(b)   c(b)

    //          /             /

    //           c(r)       a(b)

    RBNode<T>* LLLCaseA(RBNode<T>* x)

    {

        RRRotate(x,x->right);

        x->color = BLACK;

        x->parent->color = RED;

        x->parent->right->color = BLACK;

        return x->parent;

    }

    //     x(r)                b(r)

    //     /  /                /  /

    //   b(b) `a(b)-->       c(b) x(b)

    //    /                         /

    //  c(r)                        a(b)

    RBNode<T>* RLLCaseA(RBNode<T>* x)

    {

        LLRotate(x,x->left);

        x->color = BLACK;

        x->parent->color = RED;

        x->parent->left->color = BLACK;

        return x->parent;

    }

    //     x(r)                c(r)

    //     /  /                /  /

    //   b(b) `a(b)-->       b(b) x(b)

    //    /                         /

    //    c(r)                        a(b)

    RBNode<T>* RLRCaseA(RBNode<T>* x)

    {

        LRRotate(x,x->left,x->left->right);

        x->color = BLACK;

        

        return x->parent;

    }

    

    //     x(r)                     x(b)

    //     /  /                     /  /

    //   `a(b) c(b)        ->     a(b) c(r)

    //         /   /                  /   /

    //        d(b)  e(b)            d(b)  e(b)

    RBNode<T>* LCaseB(RBNode<T>* x)

    {

        x->color = BLACK;

        x->right->color = RED;

    }

    //     x(r)                     x(b)

    //     /  /                     /  /

    //    c(b) `a(b)       ->     c(r) a(b)

    //   /   /                   /   /

    // d(b)  e(b)              d(b)  e(b)

    RBNode<T>* RCaseB(RBNode<T>* x)

    {

        x->color = BLACK;

        x->left->color = RED;

    }

    //     x(b)                    c(b)

    //     /  /                    /  /

    //  `a(b)  c(r)      ->     x(r)  e(b)

    //        /   /             /  / 

    //       d(b)  e(b)      `a(b)  d(b)

    RBNode<T>* LCaseC(RBNode<T>* x)

    {

        RRRotate(x,x->right);

        x->color = RED;

        x->parent->color = BLACK;

        return  x->parent;

    }

    //     x(b)                    c(b)

    //     /  /                    /  /

    //   c(r) `a(b)     ->       d(b) x(r)

    //   /   /                        /  / 

    //  d(b)  e(b)                  e(b) `a(b) 

    RBNode<T>* RCaseC(RBNode<T>* x)

    {

        LLRotate(x,x->left);

        x->color = RED;

        x->parent->color = BLACK;

        return  x->parent;

    }

    *

    */

    bool isBlack(RBNode<T>* node)

    {

        if(node == NULL || node->color == BLACK)

            return true;

        return false;

    }

    void rebuild(RBNode<T>* node)

    {

        if(node->parent->data > node->data)

        {

            node->parent->left = node;

        }

        else

        {

            node->parent->right = node;

        }

    }

    /*

    * There are 9 cases we will meet. The cases of the double black node at the right is ignored.

    * (b) means black node, (db) means double black node, (r) means red node

    * 1.    (b)              2   (b)           3 (b)

    *      /   /                 /  /            /  /

    *    (db)  (b)             (db)  (b)       (db)  (b)

    *          /  /                  / /             / /

    *         (b)  (b)             (r)  (b)        (b)  (r)

    *

    * 4.    (b)              5   (b)           6 (r)

    *      /   /                 /  /            /  /

    *    (db)  (b)             (db)  (r)       (db)  (b)

    *          /  /                  / /             / /

    *         (r)  (r)             (b)  (b)        (b)  (b)

    *

    * 7.    (r)              8   (r)           9 (r)

    *      /   /                 /  /            /  /

    *    (db)  (b)             (db)  (b)       (db)  (b)

    *          /  /                  / /             / /

    *         (r)  (b)             (b)  (r)        (r)  (r)

    *

    * case 1,6: up the black, if the parent is black then call the function again until the 

    * double black node is root, else blacken the parent.

    * case 2,4,7,9: call the RLRotate, if the parent of the double

    * node is black, up the black and call the function again, else 

    * blacken the parent.

    * case 3,8: call the LLRotate, the same as case 2.

    * case 5: call LLRotate, change as    (b)   then end.

    *                                    /   / 

    *                                  (b)    (b)

    *                                  / /

    *                                (b)  (r)

    * 

    */

    void deleteRebuild(RBNode<T>* node,RBNode<T>* parent)

    {

        if(parent == NULL)

        {

            // root, delete the black

            return;

        }

        if(parent->left == node)

        {

            RBNode<T>* brother = parent->right;

            RBNode<T>* nephewA = brother->left;

            RBNode<T>* nephewB = brother->right;

            

            if(isBlack(nephewA) && isBlack(nephewB) && isBlack(brother))

            {

                // case 1,6

                brother->color = RED;

                if(parent->color == BLACK)

                {

                    deleteRebuild(parent,parent->parent);

                }

                else

                {

                    parent->color = BLACK;

                    return;

                }

                

            }

        

            else if(!isBlack(nephewA))

            {

                // case 2,4,7,9

                RBNode<T>* tempRoot = RLRotate(parent,brother,nephewA);

                // rebuild

                rebuild(tempRoot);

            }

            else if(!isBlack(nephewB))

            {

                // case 3,8

                RBNode<T>* tempRoot = RRRotate(parent,brother);

                rebuild(tempRoot);

                nephewB->color = BLACK;

                brother->color = RED;

            }

            else if(!isBlack(brother))

            {

                // case 5

                RBNode<T>* tempRoot = RRRotate(parent,brother);

                rebuild(tempRoot);

                brother->color = BLACK;

                nephewA->color = RED;

                return;

            }

            else

            {

                // unknown 

                throw "none excption, about there is no red or black";

            }

            if(parent->color == BLACK)

            {

                // case 2,3,4

                deleteRebuild(parent,parent->parent);

            }

            else

            {

                // case 7,8,9

                parent->color = BLACK;

            }

        }

        else

        {

            RBNode<T>* brother = parent->left;

            RBNode<T>* nephewA = brother->right;

            RBNode<T>* nephewB = brother->left;

            if(isBlack(nephewA) && isBlack(nephewB) && isBlack(brother))

            {

                brother->color = RED;

                if(parent->color == BLACK)

                {

                    deleteRebuild(parent,parent->parent);

                }

                else

                {

                    parent->color = BLACK;

                    return;

                }

            }

            else if(!isBlack(nephewA))

            {

                RBNode<T>* tempRoot = LRRotate(parent,brother,nephewA);

                // rebuild

                rebuild(tempRoot);

            }

            else if(!isBlack(nephewB))

            {

                RBNode<T>* tempRoot = LLRotate(parent,brother);

                rebuild(tempRoot);

                nephewB->color = BLACK;

                brother->color = RED;

            }

            else if(!isBlack(brother))

            {

                RBNode<T>* tempRoot = LLRotate(parent,brother);

                rebuild(tempRoot);

                nephewA->color = RED;

                brother->color = BLACK;

                return;

            }

            else

            {

                throw "none excption, about there is no red or black";

            }

            if(parent->color == BLACK)

            {

                deleteRebuild(parent,parent->parent);

            }

            else

            {

                parent->color = BLACK;

            }

        }

        

    }

    

    

    void insertNode(RBNode<T>* node)

    {

        if(root == NULL)

        {

            root = node;

            node->color = BLACK;

            return;

        }

        RBNode<T>* subRoot = root;

        RBNode<T>* insertPoint = NULL;

        while(subRoot!=NULL)

        {

            insertPoint = subRoot;

            if(subRoot->data > node->data)

            {

                // insert left

                subRoot = subRoot->left;

            }

            else if(subRoot->data < node->data)

            {

                subRoot = subRoot->right;

            }

            else

            {

                throw "same key";

            }   

        }

        

        if(insertPoint->data > node->data)

        {

            insertPoint->left = node;

        }

        else

        {

            insertPoint->right = node;

        }

        node->parent = insertPoint;

        

        

        insertRebuild(node);

        

    }

    // return the subRoot

    //        a                   b

    //       /                  /   /

    //      b        ->        c     a

    //     /

    //    c

    RBNode<T>* LLRotate(RBNode<T>* a, RBNode<T>* b)

    {

        if(b->right != NULL)

        {

            b->right->parent = a;

            

        }

        a->left = b->right;

        b->right = a;

        b->parent = a->parent;

        a->parent = b;

        return b;

    }

    // return the subRoot

    //        a                      b

    //          /                  /   /

    //            b        ->     a     c

    //              /

    //                c

    RBNode<T>* RRRotate(RBNode<T>* a, RBNode<T>* b)

    {

        if(b->left != NULL)

        {

            b->left->parent = a;

            

        }

        a->right = b->left;

        b->left = a;

        b->parent = a->parent;

        a->parent = b;

        return b;

    }

    // return the subRoot

    //        a                      c

    //          /                  /   /

    //            b        ->     a     b

    //           /                 /      

    //          c                   d  

    //         /

    //        d

    RBNode<T>* RLRotate(RBNode<T>* a, RBNode<T>* b, RBNode<T>* c)

    {

        

        if(c->right != NULL)

        {

            c->right->parent = b;       

            

        }

        b->left = c->right;

        c->right = b;

        b->parent = c;

        if(c->left != NULL)

        {

            c->left->parent = a;        

            

        }

        a->right = c->left;

        c->left = a;

        c->parent = a->parent;

        a->parent = c;

        

        return c;

    }

    // return the subRoot

    //        a                      c

    //       /                     /   /

    //      b              ->     b     a

    //       /                         /       

    //        c                       d   

    //         /

    //          d

    RBNode<T>* LRRotate(RBNode<T>* a, RBNode<T>* b, RBNode<T>* c)

    {

        if(c->left != NULL)

        {

            c->left->parent = b;

            

            

        }

        b->right = c->left;

        c->left = b;

        b->parent = c;

        if(c->right!= NULL)

        {

            c->right->parent = a;

            

        }

        a->left = c->right;

        c->right = a;

        c->parent = a->parent;

        a->parent = c;

        

        return c;

    }

    // node is not the root

    void insertRebuild(RBNode<T>* node)

    {

        RBNode<T>* parent = NULL;

        RBNode<T>* grandParent = NULL;

        while(node->parent != NULL)

        {

            parent = node->parent;

            

            if(parent->color == RED)// here means there must be a grandparent

            {

                grandParent = parent->parent;

                grandParent->color = BLACK;

                

                if(grandParent->left == parent)

                {

                    if(parent->left == node)

                    {

                        //LLRotate

                        node->color = BLACK;

                        node = LLRotate(grandParent,parent);

                        

                    }

                    else

                    {

                        //LRRotate

                        parent->color = BLACK;

                        node = LRRotate(grandParent,parent,node);

                        

                    }

                    

                }

                else

                {

                    if(parent->left == node)

                    {

                        //RLRotate          

                        parent->color = BLACK;

                        node = RLRotate(grandParent,parent,node);

                    }

                    else

                    {

                        //RRRotate

                        node->color = BLACK;

                        node = RRRotate(grandParent,parent);

                    }

                }

            }

            else

            {

                break;

            }

        }

        if(node->parent == NULL)

        {

            node->color = BLACK;

            this->root = node;

        }

        else

        {

            rebuild(node);

            /*if(node->parent->data > node->data)

            {

                node->parent->left = node;

            }

            else

            {

                node->parent->right = node;

            }*/

        }

    }

    int getBlackNum(RBNode<T>* subRoot)

    {

        if(subRoot == NULL)

        {

            return 1;

        }

        int left = getBlackNum(subRoot->left);

        int right = getBlackNum(subRoot->right);

        if(left != right)

        {

            throw "wrong";

        }

        if(subRoot->color == BLACK)

        {

            

            return 1+left;

        }

        else

        {

            return left;

        }

    }

};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  编程 null 算法 date insert c