实现红黑树

红黑树是一个比较常用到数据结构,是一个比AVL树有着更好的搜索能力的树形结构。
  1. 红黑树是一种自平衡二叉查找树
    典型的用途是实现关联数组。它是复杂的,但它的操作有着良好的最坏情况运行时间,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n 是树中元素的数目。

  2. 红黑树是一种很有意思的平衡检索树
    它的统计性能要好于平衡二叉树(AVL-树),因此,红黑树在很多地方都有应用。在C++ STL中,很多部分(目前包括set, multiset, map, multimap)应用了红黑树的变体(SGI STL中的红黑树有一些变化,这些修改提供了更好的性能,以及对set操作的支持)。

红黑树的每个节点上的属性除了有一个key、3个指针:parent、lchild、rchild以外,还多了一个属性:color。它只能是两种颜色:红或黑。而红黑树除了具有二叉搜索树的所有性质之外,为了方便计算和统计节点的个数,增加了lcount和rcount。具有以下4点性质:

  1. 根节点是黑色的。
  2. 空节点是黑色的(红黑树中,根节点的parent以及所有叶节点lchild、rchild都不指向NULL,而是指向一个定义好的空节点)。
  3. 红色节点的父、左子、右子节点都是黑色。
  4. 在任何一棵子树中,每一条从根节点向下走到空节点的路径上包含的黑色节点数量都相同。

需要说明的是:红黑树并不是一个红黑交替的树型结构,第一红黑树的性质并没有保证说是不能有两个连续的黑色节点;第二在我们删除的时候是可能存在删除掉了红色节点, 是有可能有连续的两个黑色节点的可能。

#ifndef __RB_TREE_H
#define __RB_TREE_H
#include <iostream>
#include <functional>

struct key
{
    int a;
};
typedef key KeyType;

struct RBTNode 
{
    bool    color;
    int     lcount;
    int     rcount;
    KeyType key;
    RBTNode * leftchild;
    RBTNode * rightchild;
    RBTNode * parent;
};
class RBTree
{
public:
    RBTree(RBTNode * p = NULL)
        :m_root(NULL),
        m_null(new RBTNode)
    {
        m_null->color = BLACK;
        m_root = m_null;
    }
    ~RBTree()
    {
        clear();
        delete m_null;
    }
    bool insert(const KeyType & x)
    {
        RBTNode * node = new RBTNode;
        node->key    = x;
        node->lcount = 0;
        node->rcount = 0;
        node->leftchild = m_null;
        node->rightchild = m_null;
        //node->parent = m_null;
        node->color = RED; // new node should set red to keep 
                           //each path has the number of black node

        RBTNode * p   = m_root;
        RBTNode * leaf = m_null;

        while ( p != m_null){ // find the leaf position
            leaf = p;
            if (keycmp (node->key,p->key) < 0){
                p->lcount++;
                p = p->leftchild;
            } else if (keycmp(node->key,p->key) > 0){
                p->rcount++;
                p = p->rightchild;
            } else if(keycmp(node->key,p->key) == 0) {
                return false;
            }
        }
        node->parent = leaf; // connection the tree of the leaf
        if(leaf == m_null){
            m_root = node;
        } else if( keycmp( node->key,leaf->key) < 0){
            leaf->leftchild = node;
        } else {
            leaf->rightchild = node;
        }

        insbalance(node);

        return true;
    }
    bool del(const KeyType & x)
    {
        RBTNode *node = search(x);
        if(node == NULL) return false;
        RBTNode * toDel = node;
        if(node->leftchild != m_null && node->rightchild != m_null){
            toDel = Next(node);
        } // double branch

        RBTNode *p = toDel; // adujust the number of the child count
        while (p->parent != m_null){ 
            if(p == p->parent->leftchild){
                p->parent->lcount--;
            } else {
                p->parent->rcount--;
            }
            p = p->parent;
        } //end while adjust the number of the number

        // single branch
        RBTNode *replace = toDel->leftchild != m_null ? 
                    toDel->leftchild:
                    toDel->rightchild;

        replace->parent = toDel->parent; // find the parent node
        if(replace->parent == m_null){ //m_root
            m_root = replace;
        } else if( toDel == toDel->parent->leftchild){
            replace->parent->leftchild = replace;
        } else {
            replace->parent->rightchild = replace;
        }

        if(toDel != node ){ // replace the key value
            node->key = toDel->key;
        }

        if(toDel->color == BLACK){ // this the only case ,need to reblace the tree  
            delbalance(replace);
        }

        delete toDel;
        return true;
    }
    RBTNode *atIndex(int i)
    {
        RBTNode * result = m_root;
        if( i > result->lcount + result->rcount){
            return NULL;
        } else {
            while( i != result ->lcount){
                if(i < result->lcount){
                    result = result->leftchild;
                } else {
                    i -= result->lcount +1; // 直接掉过左分支
                    result = result->rightchild;
                }
            }
        }
    }
    void toArray(int *arr)
    {
        RBTNode * p = Min();
        int i = 0;
        while (p != m_null){
            arr[i++] = p->key.a;
            p = Next(p);
        }
    }
    RBTNode * Max() const 
    {
        RBTNode * p = m_root;
        while ( p->rightchild != m_null){
             p = p->rightchild;
        }

        return  p;
    }
    RBTNode* Min()const 
    {
        RBTNode *p = m_root;
        while (p->leftchild != NULL){
             p = p->leftchild;
        }

        return p;
    }
    int size()const 
    {
        return m_root != m_null ? 
            m_root->lcount + m_root->rcount + 1 : 0;
    }
    RBTNode * search(const KeyType & key)
    {
        RBTNode * p = m_root;
        while( p != m_null && keycmp(key,p->key) != 0){
             p = keycmp(key,p->key)<0 ? p->leftchild :p->rightchild;
        }

        return p == m_null ? NULL :p;
    }

private:
    void delbalance(RBTNode *node)
    {
        RBTNode *p = node;
        while ( p != m_root && p->color == BLACK){
            if(p == p->parent->leftchild){ // find the node of node's brother
                RBTNode *sibling = p->parent->rightchild;
                if(sibling->color == RED){ // 
                    sibling->color = BLACK;
                    p->parent->color = RED;
                    leftRotate(p->parent);
                    sibling = p->parent->rightchild;
                }
                if(sibling->leftchild->color == BLACK &&
                    sibling->rightchild->color == BLACK){
                    sibling->color = RED;
                    p = p->parent;
                } else {
                    if(sibling->rightchild->color == BLACK){
                        sibling->leftchild->color = BLACK;
                        sibling->color = RED;
                        rightRotate(sibling);
                        sibling = sibling->parent;
                    }
                    sibling->color = sibling ->parent->color;

                    sibling->parent->color = BLACK;
                    sibling->rightchild->color = BLACK;
                    leftRotate(sibling->parent);
                    p = m_root;
                }
            } else {
                RBTNode *sibling = p->parent->leftchild;
                if(sibling->color == RED){
                    sibling->color = BLACK;
                    p->parent->color = RED;
                    rightRotate(p->parent);
                    sibling = p->parent->leftchild;
                }
                if(sibling->leftchild->color == BLACK &&
                    sibling->rightchild->color == BLACK){
                    sibling->color = RED;
                    p = p->parent;
                } else {
                    if(sibling->leftchild->color == BLACK){
                        sibling->rightchild->color = BLACK;
                        sibling->color = RED;
                        leftRotate(sibling);
                        sibling = sibling->parent;
                    }
                    sibling->color = sibling->parent->color;
                    sibling->parent->color = BLACK;
                    sibling->leftchild->color = BLACK;
                    rightRotate(sibling->parent);
                    p = m_root;
                }
            }
        }
        p->color = BLACK;
    }
    inline void leftRotate(RBTNode * node )
    {
        RBTNode *newroot = node->rightchild;
        node->rightchild = newroot->leftchild;
        node->rcount = newroot->lcount;  // newroot left to node's right 
        newroot->leftchild->parent = node;
        newroot->parent = node->parent;
        if(newroot->parent == m_null){
            m_root = newroot;   
        } else if(node == node->parent->leftchild){
            node->parent->leftchild = newroot;
        } else {
            node->parent->rightchild = newroot;
        }
        newroot->leftchild = node;
        newroot->lcount += node->lcount+1;
        node->parent = newroot;

    }
    inline void rightRotate(RBTNode *node)
    {
        RBTNode * newroot = node->leftchild;
        node->leftchild   = newroot->rightchild;
        node->lcount = newroot->rcount;
        node->leftchild->parent = node;
        newroot->parent = node->parent;

        if(newroot->parent == m_null){
            m_root = newroot;
        } else if (node == node->parent->leftchild){
            node->parent->leftchild = newroot;
        } else {
            node->parent->rightchild = newroot;
        }
        newroot->rightchild = node;
        newroot->rcount += node->rcount +1;
        node->parent = newroot;
    }
    void insbalance(RBTNode *node)
    {
        RBTNode *z = node;
        while( z->parent->color == RED){
            if(z->parent == z->parent->parent->leftchild){
                RBTNode *uncle = z->parent->parent->rightchild;
                if(uncle->color == RED){  // uncle is red ,to set the color of black: p->parent and uncle , set the p->parent->parent black 
                    z->parent->color = BLACK;
                    uncle->color = BLACK;
                    z->parent->parent->color = RED;
                    z = z->parent->parent; // circle to the rebalance : z = z->parent->parent
                } else {
                    if( z == z->parent->rightchild) { // if z is the right of the parent
                        z = z->parent;
                        leftRotate(z);
                    }
                    z->parent->color = BLACK;
                    z->parent->parent->color = RED;
                    rightRotate(z->parent->parent);
                }
            } else {
                RBTNode *uncle = z->parent->parent->leftchild;
                if(uncle->color == RED){
                    z->parent->color = BLACK;
                    uncle->color = BLACK;
                    z->parent->parent->color = RED;
                    z = z->parent->parent;
                } else {
                    if( z == z->parent->leftchild){
                        z = z->parent;
                        rightRotate(z);
                    } 
                    z->parent->color = BLACK;
                    z->parent->parent->color = RED;
                    leftRotate(z->parent->parent);
                }
            }
        }

        m_root->color = BLACK;
    }
    RBTNode *left(RBTNode * node)
    {
        RBTNode * result = node;
        while (result ->leftchild != m_null){
            result = result->leftchild;
        }
        return result;
    }
    RBTNode *right(RBTNode *node)
    {
        RBTNode * result = node;
        while (result ->rightchild != m_null){
            result = result->rightchild;
        }

        return result;
    }
    RBTNode *Next(RBTNode *node)
    {
        if(node == NULL) return NULL;

        RBTNode * p = node;
        if(p->rightchild != m_null){
            p = left(p->rightchild);
        } else {
             p = node->parent;
             RBTNode * temp = node;
             while( p != m_null && temp == p->rightchild ){
                temp = p;
                p = p->parent;
             }
        }

        return p;
    }
    RBTNode *Prev(RBTNode *node)
    {
        if(node == NULL ) return NULL;
        RBTNode * result = node;    
        if(result ->leftchild != m_null){
            result = left(result->rightchild);
        } else {
            result = node->parent;
            RBTNode *temp = node;
            while (result != m_null && temp == result->leftchild){
                temp = result;
                result = result->parent;
            }
        }

        return result;
    }
    inline int keycmp(const KeyType & key1,const KeyType & key2)
    {
        return key1.a - key2.a;
    }
    void clear()
    {
        RBTNode * p = m_root;
        while(p != m_null){
            if(p->leftchild != m_null){
                p = p->leftchild;
            } else if ( p->rightchild != m_null){
                p = p->rightchild;
            } else {
                RBTNode *temp = p;
                p = p->parent;
                if(temp == p->leftchild){
                    p->leftchild  = m_null;
                } else {
                    p->rightchild = m_null;
                }
                delete temp;
            }
        }
    }
private:
    const static bool RED = true;
    const static bool BLACK = false;
    RBTNode * m_root;
    RBTNode * m_null;
};

#endif

简单的测试:

#include "RBTree.hpp"
#include <iostream>
using namespace std;

int main()
{
    RBTree tree;
    KeyType ar[] = {2,45,56,34,54,232,56,567,33,34,56,232,23,44};
    int len = sizeof(ar)/sizeof(ar[0]);
    for(int i = 0; i< len ;i++){
        cout<<tree.insert(ar[i]);
    }

    cout<<endl;
    for(int i = 0; i <len;i++){
        cout<<tree.del(ar[i]);
    }

    return 0;
}

详细的解析请看附带的pdf文件

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值