红黑树
红黑树是很多平衡树的一种,保证最坏情况下基本动态几何操作时间复杂度为O(log(n))
1、红黑树性质
(1) 每个节点是红色的,或者是黑色的
(2) 根节点是黑色的
(3) 每个叶节点(nil)是黑色的
(4) 如果一个节点是黑色的,则它的连个子节点都是黑色的
(5) 对每个节点,从该节点到其后代叶节点的简单路径上,均包含相同数目的黑色节点
2、旋转
旋转是保持二叉搜索树局部性质的操作,包括左旋和右旋。当在节点x上做左旋时,假设它的右孩子为y而不是T.nil,X可为其右孩子不是T.nil的任何节点,同理,X做右旋也是一样的。
伪代码如下(左旋)
旋转代码(左旋-C)
static void left_rotate(rbTree *T, rbtreeNode * x)
{
rbtreeNode *y = x->right;
x->right = y->left;
if(y->left != T->nil)
y->left->p = x;
y->p = x->p;
if(x->p == T->nil)
T->root = y;
else if(x == x->p->left)
x->p->left = y;
else
x->p->right = y;
y->left = x;
x->p = y;
}
3、插入
在O(log(n))时间内插入一个节点,RB-INSERT过程完成该操作,像一个普通的二叉搜索树一样,然后将要插入的节点Z着为红色。为了保持红黑树的性质,调用一个辅助函数RB-INSERT-FIXUP来对节点从新着色并旋转。待插入节点Z已保存了数据项。
RB-INSERT过程伪代码
RB-INSERT-FIXUP过程伪代码
注意:Case1属于if判断条件中,Case2和Case3输入else语句中的,Case2是else语句中的if判断语句的。具体可以看代码
RB-INSERT代码实现(C)
int rbtree_insert(rbTree *T, DataTypedef num)
{
rbtreeNode *y = T->nil;
rbtreeNode *x = T->root;
rbtreeNode *z = NULL;
if(!rbtree_in(T, num))
{
z = (rbtreeNode *)malloc(sizeof(rbtreeNode));
if(z == NULL)
err_sys("no space for z in rbtree");
z->data = num;
}
else
return ERR;
while(x != T->nil) //y is parent point of x
{
y = x;
if(z->data < x->data)
x = x->left;
else
x = x->right;
}
z->p = y;
if(y == T->nil)
T->root = z;
else if(z->data < y->data)
y->left = z;
else
y->right = z;
z->left = T->nil;
z->right = T->nil;
z->color = RED;
if( rbtree_fixup(T, z) )
return OK;
else
return ERR;
}
RB-INSERT-FIXUP过程分析