vlambda博客
学习文章列表

红黑树的基本性质和旋转

红黑树的五个性质:

1,每个结点为红色或者为黑色。

2,根结点为黑色

3,叶子结点为黑色

4,红色结点的两个儿子结点为黑色

5,对于每个结点,它的每条路径上有相同数目的黑色结点。

数据结构如下:

typedef int KEY_TYPE;

typedef struct _rbtree_node{

    unsigned char color;

    KEY_TYPE value;

    struct rbtree_node* left;

    struct rbtree_node* right;

    struct rbtree_node* parent;

}rbtree_node;

typedef struct _rbtree{

    struct _rbtree_node* root;

    struct _rbtree_node* nil;

}rbtree;

当我们插入一个结点时,默认其颜色为红色,如果插到黑色结点下面,可不用变化树形。

如果插入到红色结点下,因为不满足第4条性质,所以需要变色或者是旋转。

我们这一篇先讨论旋转,旋转分为,左旋和右旋。

左旋:


只需要三步即可完成左旋,安排!

Node* y = x ->right;

①安排y->left。

   将y->left 给给 x->left

    判断y->left是否存在,如果存在,将x作为 y->left->parent

②安排y->parent

    将x->parent 给给 y->parent

    需要判断,x是不是根节点,即判断x->parent是否为空,

    若是,则把y作为新的根结点。

    若不是,判断x是父节点的左/右孩子,将y 作为 父节点的左右孩子。

③安排y

    将x 作为 y->left

    将y 作为 x->parent

    左旋代码:

void rotate_left(rbtree* T, rbtree_node* x){ rbtree_node* y = x->right; x->right = y->left; if(y->left){ y->left->parent = x; }  y->parent = x->parent; if(x->parent == T->nil){ T->root = y; }else if(x == x->parent->left){ x->parent->left = y; }else{ x->parent->right = y; }  y->left = x; x->parent = y; }


右旋:

只需要三步也可完成右旋,继续安排!

Node* y =x->left;

①安排y->right

    将y>right 给给x->left

    如果y->right 存在,则把x作为 y->right->parent

②安排y->parent

    将x->parent 给给y->parent

    需要判断,x是不是根节点,即判断x->parent是否为空

    若是,则将y作为新的根结点

    若不是,则判断x是其父节点的左/右孩子,同时将y作为其父节点的左右孩子。

③安排x

    将x给给y->right

    将y作为x->parent。

右旋代码:

void rotate_left(rbtree* T, rbtree_node* x){ rbtree_node* y = x->left; x->left= y->right; if(y->right){ y->right->parent = x; }  y->parent = x->parent; if(x->parent == T->nil){ T->root = y; }else if(x == x->parent->right){ x->parent->right= y; }else{ x->parent->left= y; }  y->right= x; x->parent = y; }