1. 程式人生 > >通俗易懂看RB-tree(二)

通俗易懂看RB-tree(二)

RB-tree結點設計

codes:

typedef bool rb_tree_color_type
const rb_tree_color_type rb_tree_red=false;
const rb_tree_color_type rb_tree_black=true;
struct rb_tree_node_base  
{
    typedef rb_tree_color_type color_type;//顏色種類
    typedef rb_tree_node_base *base_ptr;//紅黑樹節點指標
    
    color_type color;
    base_ptr parent;
    base_ptr left;
    base_ptr right;
};

迭代器設計

codes:
void increment//前進,含義是找到比當前結點大的元素中最小的元素
{
    if(node->right!=0)
    {
        node=node->right;
        while(node->left!=0)
            node=node->left;
    }
    else
    {
        base_ptr y=node->parent;
        while(node==y->right)//若此時是y的右節點,則一直向上遞迴
        {
            node=y;
            y=y->parent;
        }
        /*此時node為y的左節點,而node的右節點和y都大於node
        所以當node的右節點不等於y 時,返回y;(若相等,出錯)*/
        if(node->right!=y)
            node=y;

    }
}
void decrement//後退,含義是找比當前元素小的元素中最大的元素
{
    if(node->color==rb_tree_red&&node->parent->parent==node)
        node=node->right;//此處node是根節點
    else if(node->left!=0)
    {
        base_ptr y=node->left;
        while(y->right!=0)
            y=y->right;
        node=y;
    }
    else
    {
        //若沒有左節點,則判斷該節點是否是左節點,向上遞迴,直到該節點為右節點停止;
        //由二叉搜尋樹的性質,節點只要在右子樹上,就肯定比父節點大,所以尋找以該節點為右子樹的父節點;
        base_ptr y=node->parent;
        while(node==y->left)
        {
            node=y;
            y=y->parent;
        }
        node=y;
    }
}

調整RB-tree(旋轉及改變顏色)

inline void rb_tree_rebalance(rb_tree_node_base*x,rb_tree_node_base *&root)
{
    x->color=rb_tree_red;//新節點必為紅色;
    while(x!=root&&x->parent->color==rb_tree_red)
    {
        if(x->parent==x->parent->parent->left)
        {
            rb_tree_node_base *y=x->parent->parent->right;//令y為伯父節點;
            if(y&&y->color==rb_tree_red)
            {
                x->parent->color=rb_tree_black;
                y->color=rb_tree_black;
                x->parent->parent->color=rb_tree_red;
                x=x->parent->parent;
            }
            else
            {
                //無伯父節點,或伯父節點為黑;
                if(x==x->parent->right)//此時是內側插入
                {
                    x=x->parent;
                    rb_tree_rotate_left(x,root);
                }
                x->parent->color=rb_tree_black;
                x->parent->parent=rb_tree_red;
                rb_tree-rotate_right(x->parent->parent,root);
                
            }
            else//父節點為祖父節點之右節點;
            {
                rb_tree_node_base *y=x->parent->parent->left;
                if(y&&y->color==rb_tree_red)
                {
                    x->parent->color=rb_tree_black;
                    y->color=rb_tree_black;
                    x->parent->parent=rb_tree_red;
                    x=x->parent->parent;
                }
                else//無伯父節點,或者伯父節點為黑
                {
                    if(x==x->parent->left)
                    {
                        x=x->parent;
                        rb_tree_rotate_right(x,root);
                    }
                    x->parent->color=rb_tree_black;
                    x->parent->parent->color=rb_tree_red;
                    rb_tree_rotate_left(x->parent->parent,root);
                }
            }
        }
    }
    root->color=rb_tree_black;//根節點永遠為黑色;
    
}

//左旋轉

inline void rb_tree_rotate_left(rb_tree_node_base *x,rb_tree_node_base *&root)
{
    //x為旋轉點;
    rb_tree_node_base *y=x->right;//y為旋轉點的右子結點
    x->right=y->left;
    if(y->left!=0)
        y->left->parent=x;
    y->parent=x->parent;
    
    //y要完全代替x的地位,將x的所有關係完全接收過來;
    if(x==root)
        rooy=y;
    else if(x==x->parent->left)
        x->parent->left=y;
    else
        x->parent->right=y;
    y->left=x;
    x->parent=y;
}
//右旋轉
inline void rb_tree_rotate_right(rb_tree_node_base *x,rb_tree_node_base *&root)
{
    rb_tree_node_base *y=x->left;
    x->left=y->right;
    if(y->right!=0)
        y->right->paren=x;
    y->parent=x->parent;
    
    if(x==root)
        root=y;
    else if(x=x->parent->left)
        x->parent->left=y;
    else
        x->parent->right=y;
    y->right=x;
    x->parent=y;
}