算法导论学习笔记(三)红黑树

算法导论学习笔记(三)红黑树

红黑树是众多平衡二叉树的一种,顾名思义,它由红黑两种节点构成;
它有以下五点性质:
1. 每个节点或是红色的,或是黑色的;
2. 根节点是黑色的;
3. 每个叶节点(NIL)是黑色的;
4. 如果一个节点是红色的,则其两个子节点都是黑色的;
5. 对于每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点。
当满足以上5个性质的红黑树,就能保证没有一条路径会比其他路径长2倍以上,因而可看作近似平衡。


红黑树是我目前所见过的数据结构中,最为复杂的一种,目前只能初步了解其意图,而不知其真正的原理,故以下代码仍有不足——为经过完整测试,部分代码可能有错。


伪代码

RED-BLACK-INSERT(T, z)
    y = T.nil
    x = T.root
    while x != T.nil
        y = x
        if z.key < x.key
            x = x.left
        else x = x.right
    z.father = y
    if y == T.nil
        T.root = z
    elseif z.key < y.key
        y.left = z
    else y.right = z
    z.right = T.nil
    z.left = T.nil
    z.color = RED
    RED-BLACK-TREE-INSERT-FIXUP(T, z)

RED-BLACK-TREE-INSERT-FIXUP(T, z)
    while z.father.color == RED
        if( z.father == ( (z.father).father).left )
            y = ( (z.father).father).right
            if( y.color == RED)
                (z.father).color = BLACK
                y.color = BLACK
                ( (z.father).father).color = RED
                z = (z.father).father
            else 
                if z == (z.father).right
                    z = z.father
                    LEFT-ROTATE(T,z)
                (z.father).color = BLACK
                ( (z.fater).father).color = RED
                RIGHT-ROTATE(T, (z.father).father)
        else
            y = ( (z.father).father).left
            if( y.color == RED)
                (z.father).color = BLACK
                y.color = BLACK
                ( (z.father).father).color = RED
                z = (z.father).father
            else
                if z == (z.father).left
                    z = z.fahter
                    RIGHT-ROTATE(T, z)
                (z.father).color = BLACK
                ( (z.father).father).color = RED
                LEFT-ROTATE(T, (z.father).fater)

LEFT-ROTATE(T, x)
    y = x.right

    y.father = x.father
    if x.father == T.nil
        T.root = y
    elseif x == (x.father).left
        (y.father).left = y
    else (y.father).right = y

    x.right = y.left
    if x.right != T.nill
        (x.right).father = x

    y.left = x
    x.father = y

RIGHT-ROTATE(T, x)
    y = x.left

    y.father = x.father
    if x.father == T.nil
        T.root = y
    elseif x == (x.father).right
        (x.father).right = y
    else (x.father).left = y

    x.left = y.right
    if x.left != T.nil
        (x.left).father = x

    y.right = x
    x.father = y

RED-BLACK-DELETE( T, z )
    y = z
    y-original-color = y.color
    if z.left == T.nil
        x = z.right
        RED-BLACK-TRANSPLANT( T, z, z.right )
    elseif z.right == T.nil
        x = z.left
        RED-BLACK-TRANSPLANT( T, z, z.left )
    else
        y = getNextTreePoint( z.right )
        y-original-color = y.color
        x = y.right
        if y.p == z
            x.p = y
        else 
            RED-BLACK-TRANSPLANT( T, y, y.right )
            y.right = z.right
            y.right.p = y
        RED-BLACK-TRANSPLANT( T, z, y )
        y.left = z.left
        y.left.p = y
        y.color = z.color
    if y-original-color == BLACK
        RED-BLACK-DELETE-FIXUP( T, x )

RED-BLACK-TRANSPLANT( T, u, v )
    if u.p == T.nil
        T.root = v
    elseif u == u.p.left
        u.p.left = v
    else 
        u.p.right = v
    v.p = u.p

RED-BLACK-DELETE-FIXUP( T, x )
    while x != T.root and x.color == BLACK
        if x == x.p.left
            w = x.p.right
            if w.color == RED
                w.color = BLACK
                x.p.color = RED
                LEFT-ROATE( T, x.p )
                w = x.p.right
            if w.left.color == BLACK and w.right.color == BLACK
                w.color = RED
                x = x.p
            else 
                if w.right.color == BLACK
                    w.left.color = BLACK
                    w.color = RED
                    RIGHT-ROATE( T, w )
                    w = x.p.right
                w.color = x.p.color
                x.p.color = BLACK
                w.right.color = BLACK
                LEFT-ROATE( T, x.p )
                x = T.root
        else
            w = x.p.left
            if w.color == RED
                w.color = BLACK
                x.p.color = RED
                RIGHT-ROATE( T, x.p )
                w = x.p.left
            if w.right.color == BLACK and w.left.color == BLACK
                w.color = RED
                x = x.p
            else
                if w.left.color == BLACK
                    w.right.color = BLACK
                    w.color = RED
                    LEFT-ROATE( T, w)
                    w = x.p.left
                w.color = x.p.color
                x.p.color = BLACK
                w.left.color = BLACK
                RIGHT-ROATE( T, x.p )
                x = T.root
    x.color = BLACK

代码实现

#include <iostream>
#define RED true
#define BLACK false
using namespace std;
struct TreePoint
{
    int key;
    bool color;
    TreePoint* father;
    TreePoint* right;
    TreePoint* left;
    TreePoint(){}
    TreePoint(int key) {
        this->key = key;
        father = NULL;
        right = NULL;
        left = NULL;
    }
};
struct RedBlackTree
{
    TreePoint* root;
    TreePoint* nil;
    RedBlackTree(){
        nil = new TreePoint();
        nil->color = BLACK;
        root = nil;
        root->father = nil;
    }
};
void leftRotate(RedBlackTree &, TreePoint* );
void rightRotate(RedBlackTree &, TreePoint* );
TreePoint* getNextTreePoint(RedBlackTree &, TreePoint*);
void transplantRedBlackTree(RedBlackTree &, TreePoint*  ,TreePoint* );

void fixUpRedBlackTreeInserting(RedBlackTree &, TreePoint*);
void insertRedBlackTree(RedBlackTree &, TreePoint* );

void fixUpRedBlackTreeDeleting(RedBlackTree &, TreePoint*);
void deleteRedBlackTree(RedBlackTree &, TreePoint* );

TreePoint* findPoint(RedBlackTree &,TreePoint* , int );
void show(RedBlackTree &, TreePoint* );


int main()
{
    RedBlackTree redBlackTree;
    int n = 10;
    cin>>n;
    //while(n--) {
    int key;
    for(int i=0;i<n;++i){
        cin>>key;
        insertRedBlackTree(redBlackTree,new TreePoint(key));
    }
    show(redBlackTree,redBlackTree.root);
    cout<<endl;
    key = 7;
    TreePoint* find = findPoint(redBlackTree,redBlackTree.root,key);

    deleteRedBlackTree(redBlackTree,find);
    show(redBlackTree,redBlackTree.root);
    cout<<endl;
}


void insertRedBlackTree(RedBlackTree &T,TreePoint* z){
    TreePoint* y = T.nil;
    TreePoint* x = T.root;
    while( x != T.nil ) {
        y = x;
        if(z->key < x->key) {
            x = x->left;
        }
        else {
            x = x->right;
        }
    }
    z->father = y;
    if (y == T.nil) {
        T.root = z;
    }
    else if(z->key < y->key) {
        y->left = z;
    }
    else {
        y->right = z;
    }
    z->right = T.nil;
    z->left = T.nil;
    z->color = RED;
    fixUpRedBlackTreeInserting(T,z);
}

void fixUpRedBlackTreeInserting(RedBlackTree &T,TreePoint* z) {
    while( (z->father)->color == RED) {
        TreePoint* y;
        if( z->father == ( (z->father)->father)->left) {
            y = ( (z->father)->father)->right;
            if( y->color == RED) {
                (z->father)->color = BLACK;
                y->color = BLACK;
                ( (z->father)->father)->color = RED;
                z = (z->father)->father;
            }
            else {
                if( z == (z->father)->right) {
                    z = z->father;
                    leftRotate(T,z);
                }
                (z->father)->color = BLACK;
                ( (z->father)->father)->color = RED;
                rightRotate(T,(z->father)->father);
            }
        }
        else {
            y = ( (z->father)->father)->left;
            if( y->color == RED) {
                (z->father)->color = BLACK;
                y->color = BLACK;
                ( (z->father)->father)->color = RED;
                z = (z->father)->father;
            }
            else {
                if( z == (z->father)->left) {
                    z = z->father;
                    rightRotate(T,z);
                }
                (z->father)->color = BLACK;
                ( (z->father)->father)->color = RED;
                leftRotate(T,(z->father)->father);
            }
        }
    }
    (T.root)->color = BLACK;
}

void deleteRedBlackTree(RedBlackTree &T, TreePoint* z) {
    TreePoint* y = z;
    TreePoint* x;
    bool originalColor_y = y->color;
    if( z->left == T.nil ) {
        x = z->right;
        transplantRedBlackTree(T,z,z->right);
    }
    else if( z->right == T.nil) {
        x = z->left;
        transplantRedBlackTree(T,z,z->left);
    }
    else {
        y = getNextTreePoint(T,z->right);
        originalColor_y = y->color;
        x = y->right;
        if( y->father == z) {
            x->father = y;
        }
        else {
            transplantRedBlackTree(T,y,y->right);
            y->right = z->right;
            (y->right)->father = y;
        }
        transplantRedBlackTree(T,z,y);
        y->left = z->left;
        (y->left)->father = y;
        y->color = z->color;
    }
    if( originalColor_y == BLACK) {
        fixUpRedBlackTreeDeleting(T,x);
    }
}

void fixUpRedBlackTreeDeleting(RedBlackTree &T, TreePoint* x) {
    while( x != T.root && x->color == BLACK) {
        TreePoint* w;
        if( x== (x->father)->left) {
            w = (x->father)->right;
            if( w->color == RED) {
                w->color = BLACK;
                (x->father)->color = RED;
                leftRotate(T,x->father);
                w = (x->father)->right;
            }
            if( (w->left)->color == BLACK && (w->right)->color == BLACK) {
                w->color = RED;
                x = x->father;
            }
            else {
                if( (w->right)->color == BLACK) {
                    (w->left)->color = BLACK;
                    w->color = RED;
                    rightRotate(T,w);
                    w = (x->father)->right;
                }
                w->color = (x->father)->color;
                (x->father)->color = BLACK;
                (w->right)->color = BLACK;
                leftRotate(T,x->father);
                x = T.root;
            }
        }
        else {
            w = (x->father)->left;
            if( w->color == RED) {
                w->color = BLACK;
                (x->father)->color = RED;
                rightRotate(T,x->father);
                w = (x->father)->left;
            }
            if( (w->right)->color == BLACK && (w->left)->color == BLACK) {
                w->color = RED;
                x = x->father;
            }
            else {
                if( (w->left)->color == BLACK) {
                    (w->right)->color = BLACK;
                    w->color = RED;
                    leftRotate(T,w);
                    w = (x->father)->left;
                }
                w->color = (x->father)->color;
                (x->father)->color = BLACK;
                (w->left)->color = BLACK;
                rightRotate(T,x->father);
                x = T.root;
            }
        }
    }
    x->color = BLACK;
}

void leftRotate(RedBlackTree &T,TreePoint* x) {
    TreePoint* y;
    y = x->right;
    y->father = x->father;
    if( x->father == T.nil) {
        T.root = y;
    }
    else if( x == (x->father)->left) {
        (y->father)->left = y;
    }
    else {
        (y->father)->right = y;
    }
    x->right = y->left;
    if( x->right != T.nil ) {
        (x->right)->father = x;
    }
    y->left = x;
    x->father = y;
    }
    void rightRotate(RedBlackTree &T,TreePoint* x) {
    TreePoint* y;
    y = x->left;
    y->father = x->father;
    if( x->father == T.nil) {
        T.root = y;
    }
    else if( x == (x->father)->right) {
        (y->father)->right = y;
    }
    else {
        (y->father)->left = y;
    }
    x->left = y->right;
    if( x->left != T.nil ) {
        (x->left)->father = x;
    }
    y->right = x;
    x->father = y;
}

void transplantRedBlackTree(RedBlackTree &T, TreePoint* u,TreePoint* v) {
    if( u->father == T.nil ) {
        T.root = v;
    }
    else if( u == (u->father)->left ) {
        (u->father)->left = v;
    }
    else {
        (u->father)->right = v;
    }
    v->father = u->father;
}

TreePoint* getNextTreePoint(RedBlackTree &T, TreePoint* x) {
    while(x->left != T.nil){
        x = x->left;
    }
    return x;
}

TreePoint* findPoint(RedBlackTree &T, TreePoint* p, int key) {
    if(p == T.nil){
        return NULL;
    }
    else if(p->key == key){
        return p;
    }
    else if(p->key > key ) {
        return findPoint(T,p->left,key);
    }
    else {
        return findPoint(T,p->right,key);
    }
}

void show(RedBlackTree &T,TreePoint* p) {
    cout<<p->key<<" ";
    if( p->left != T.nil ) {
        show(T,p->left);
    }
    //cout<<p->key<<" ";
    if( p->right != T.nil ) {
        show(T,p->right);
    }
    //cout<<p->key<<" ";
}

/*
9
11 2 14 1 15 7 5 8 4
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值