//
// 五條屬性:
// 1.每個節點或是紅色的,或是黑色的。
// 2.根節點是黑色的。
// 3.每個葉結點(NIL)是黑色的。
// 4.如果一個結點是紅色的,則它的兩個子結點都是黑色的。
// 5.對每個結點,從該結點到其所有後代葉結點的簡單路徑上
// 均包含相同數目的黑色結點。
//
//http://blog.csdn.net/v_JULY_v/article/details/6105630
//https://github.com/torvalds/linux/blob/master/lib/rbtree.c
//https://github.com/torvalds/linux/blob/master/include/linux/rbtree_augmented.h
//https://github.com/torvalds/linux/blob/master/include/linux/rbtree.h
#include "common.h"
#include "RBTree.h"
static RB_NODE* RbSearch(int key, RB_NODE* root);
static RB_NODE* RbInsert(RB_NODE* head, RB_NODE* node);
static RB_NODE* InsertFixup(RB_NODE *,RB_NODE *);
static RB_NODE* LeftRotate(RB_NODE* head, RB_NODE* node);
static RB_NODE* RightRotate(RB_NODE* head, RB_NODE* node);
static RB_NODE* RbTransplant(RB_NODE* head,RB_NODE* u,RB_NODE* v);
static RB_NODE* RbDeleteFixup(RB_NODE* head, RB_NODE* x);
static RB_NODE* RbDelete(RB_NODE* head, RB_NODE* z);
static void TreePrint(RB_NODE* head);
static void LevelOrderWalk(RB_NODE* node);
void PrintT(RB_NODE* head)
{
RB_NODE *left=NULL, *right=NULL;
RB_NODE *left1=NULL,*left2=NULL,*right1=NULL,*right2=NULL;
RB_NODE *left31=NULL,*left32=NULL,*right31=NULL,*right32=NULL,*left33=NULL,*left34=NULL,*right33=NULL,*right34=NULL;
if(head)
{
left=head->left;
right=head->right;
}
if(left)
printf("[%d]",left->key);
if(head)
printf("[%d]",head->key);
if(right)
printf("[%d]",right->key);
printf("\n-----\n");
if(left)
{
left1 = left->left;
left2 = left->right;
}
if(right)
{
right1 = right->left;
right2 = right->right;
}
if(left1)
printf("[%d]",left1->key);
if(left2)
printf("[%d]",left2->key);
if(right1)
printf("[%d]",right1->key);
if(right2)
printf("[%d]",right2->key);
printf("\n-----\n");
if(left1)
{
left31 = left1->left;
left32 = left1->right;
}
if(left2)
{
left33 = left2->left;
left34 = left2->right;
}
if(right1)
{
right31 = right1->left;
right32 = right1->right;
}
if(right2)
{
right33 = right2->left;
right34 = right2->right;
}
if(left31)
printf("[%d]",left31->key);
if(left32)
printf("[%d]",left32->key);
if(left33)
printf("[%d]",left33->key);
if(left34)
printf("[%d]",left34->key);
if(right31)
printf("[%d]",right31->key);
if(right32)
printf("[%d]",right32->key);
if(right33)
printf("[%d]",right33->key);
if(right34)
printf("[%d]",right34->key);
printf("\n-----\n");
}
void RBTree()
{
///////////////////////////////////////
//二叉樹:
// 11
// 2 14
// 1 7 15
// 5 8
// 4
///////////////////////////////////////
///////////////////////////////////////
//紅黑樹:
// 7
// 2 11
// 1 5 8 14
// 4 6 9 13 15
//
///////////////////////////////////////
int toBeInsert[] = {11,2,14,1,7,15,5,8,9,4,13,6};
int i;
RB_NODE *head = NULL;
RB_NODE * tmp = NULL;
RB_NODE* node;
for(i=0; i<sizeof(toBeInsert)/sizeof(int); i++)
{
node = (RB_NODE*)malloc(sizeof(RB_NODE));
node->key = toBeInsert[i];
head = RbInsert(head, node);
}
//TreePrint(head);
PrintT(head);
printf("\n==========\n");
for(i=0; i<sizeof(toBeInsert)/sizeof(int); i++)
{
tmp = RbSearch(toBeInsert[i],head);
if(tmp)
{
printf("%d ",tmp->key);
head = RbDelete(head, tmp);
PrintT(head);
//TreePrint(head);
printf("\n");
}
}
printf("\n");
}
//三、紅黑樹查找結點
//----------------------------------------------------
//rb_search_auxiliary:查找
//rb_node_t* rb_search:返回找到的結點
//----------------------------------------------------
static RB_NODE* RbSearchAuxiliary(int key, RB_NODE* root, RB_NODE** pre)
{
RB_NODE *node = root, *parent = NULL;
int ret;
while(node)
{
parent = node;
ret = node->key - key;
if (0 < ret)
{
node = node->left;
}
else if (0 > ret)
{
node = node->right;
}
else
{
return node;
}
}
if (pre)
{
*pre = parent;
}
return NULL;
}
//返回上述rb_search_auxiliary查找結果
RB_NODE* RbSearch(int key, RB_NODE* root)
{
return RbSearchAuxiliary(key, root, NULL);
}
RB_NODE* RbInsert(RB_NODE* head, RB_NODE* node)
{
RB_NODE *tmp = head;
RB_NODE *pre = NULL;
//二叉樹的插入動作需要先找到插入位置
while(tmp != NULL)
{
pre = tmp;
if(node->key < tmp->key)
{
tmp = tmp->left;
}
else
{
tmp = tmp->right;
}
}
if(pre == NULL)
{
head = node;
}
else if(node->key < pre->key)
{
pre->left = node;
}
else
{
pre->right = node;
}
node->p = pre;
node->color = RED;
node->left = NULL;
node->right = NULL;
head = InsertFixup(head,node);
return head;
}
//左旋,
//右孩子和top的位置調換,top成爲right的左孩子
//top的左孩子最小依然是top的左孩子
//右孩子的左孩子大於top小於右孩子,經過轉換成爲top的右孩子
//
RB_NODE* LeftRotate(RB_NODE* head, RB_NODE* top)
{
RB_NODE* right = top->right;
top->right = right->left;
if(right->left != NULL)
{
right->left->p = top;
}
right->p = top->p;
if(top->p == NULL)
{
head = right;
}
else if(top == top->p->left)
{
top->p->left = right;
}
else if(top == top->p->right)
{
top->p->right = right;
}
right->left = top;
top->p = right;
return head;
}
// 右旋 --- 將根的左孩子轉移到根的位置,原來的根成爲新的根的右孩子
//最小值a和最大值r都不變
//中間數據:x--小於原來根y,大於原來根的左孩子x。
// y x
// x r -->a y
// a b b r
//
RB_NODE* RightRotate(RB_NODE* head, RB_NODE* y)
{
RB_NODE *x = y->left;
y->left = x->right;
if(x->right != NULL)
{
x->right->p = y;
}
x->p = y->p;
if(y->p == NULL)
{
head = x;
}
else if(y == y->p->left)
{
x->p->left = x;
}
else
{
x->p->left = x;
}
x->right = y;
y->p = x;
return head;
}
//
// 五條屬性:
// 1.每個節點或是紅色的,或是黑色的。
// 2.根節點是黑色的。
// 3.每個葉結點(NIL)是黑色的。
// 4.如果一個結點是紅色的,則它的兩個子結點都是黑色的。
// 5.對每個結點,從該結點到其所有後代葉結點的簡單路徑上
// 均包含相同數目的黑色結點。
//
//如果插入的是根結點,由於原樹是空樹,此情況只會違反性質2,因此直接把此結點塗爲黑色;
//如果插入的結點的父結點是黑色,由於此不會違反性質2和性質4,紅黑樹沒有被破壞,所以此時什麼也不做。
//
//出現需要修復的情況必然是插入的結點的父結點是紅色,祖父結點是黑色
//插入修復情況1:如果當前結點的父結點是紅色且祖父結點的另一個子結點(叔叔結點)是紅色
//插入修復情況2:當前節點的父節點是紅色,叔叔節點是黑色,當前節點是其父節點的右子
//插入修復情況3:當前節點的父節點是紅色,叔叔節點是黑色,當前節點是其父節點的左子
//
static RB_NODE* InsertFixup(RB_NODE* head, RB_NODE* node)
{
RB_NODE *parnt, *grdparnt,*uncle, *tmp;
while((parnt = node->p) && parnt->color == RED)
{
//1.如果z.p(z的父結點)是其父結點的左孩子
//(1)將其父結點的右孩子設爲y
// z.p<z.p.p<y
grdparnt = parnt->p;
if(grdparnt->left == parnt)
{
uncle = grdparnt->right;
if(uncle && uncle->color == RED)
{
parnt->color = BLACK;
uncle->color = BLACK;
grdparnt->color = RED;
node = grdparnt;
// case 1:z.p爲RED
// z.p是其父結點的左孩子
// y爲z.p的右兄弟
// y爲RED(規則4)
// 將z.p和y都置爲BLACK
// 將z.p.p置爲RED
}
else
{
if(node == parnt->right)
{
head = LeftRotate(head,parnt);
tmp = parnt;
parnt = node;
node = tmp;
//case2:
//z.p爲RED
// z.p是其父節點的左孩子
// y爲z.p的右兄弟
// y爲BLACK && z是z.p的右孩子
// (規則4)
// z = z.p//指針上移
// 左旋
}
parnt->color = BLACK; //case 3
grdparnt->color = RED;
head = RightRotate(head,grdparnt);
}
}
else if (grdparnt->right == parnt)
{
uncle = grdparnt->left;
if(uncle && uncle->color == RED)
{
parnt->color = BLACK;
uncle->color = BLACK;
grdparnt->color = RED;
node = grdparnt;
}
else
{
if(node == parnt->left)
{
head = RightRotate(head,parnt);
tmp = parnt;
parnt = node;
node = tmp;
}
parnt->color = BLACK; //case 3
grdparnt->color = RED;
head = LeftRotate(head,grdparnt);
}
}
}
head->color = BLACK;
return head;
}
static RB_NODE* TreeMinmum(RB_NODE* x)
{
while(x->left != NULL)
{
x = x->left;
}
return x;
}
//
//結點替換:將u用v替換掉。
//情況1:被換結點是根,那麼根地址指向v
//情況2:被換結點是一個左孩子,
//情況3:被換結點是一個右孩子
static RB_NODE* RbTransplant(RB_NODE* head,RB_NODE* u,RB_NODE* v)
{
if(u->p == NULL)
{
head = v;
}
else if ( u == u->p->left)
{
u->p->left = v;
}
else
{
u->p->right = v;
}
if(v)
{
v->p = u->p;
}
return head;
}
///////////////////////////////////////////////////////////////////////////////////////////
//刪除:用左孩子、右孩子、後繼來替換被刪除的結點。然後根據規則進行重新修整。
// 左孩子爲空就用右孩子,右孩子爲空就用左孩子,有兩個孩子就用後繼。
//
// 紅黑樹屬性:
// 1.每個節點或是紅色的,或是黑色的。
// 2.根節點是黑色的。
// 3.每個葉結點(NIL)是黑色的。
// 4.如果一個結點是紅色的,則它的兩個子結點都是黑色的。
// 5.對每個結點,從該結點到其所有後代葉結點的簡單路徑上
// 均包含相同數目的黑色結點。
//
// //如果y(z)(被刪結點)是紅色,當y被刪除或移動時,紅黑性質仍然保持,原因如下:
// 1.樹中的黑高沒有變化。
// 2.不存在兩個相鄰的紅結點。因爲y在樹中佔據了z的位置,在考慮到z的顏色,樹中y的新位置
// 不可能有兩個相鄰的紅結點。另外,如果y不是z的右孩子,則y的原右孩子x代替y.如果y是紅色,
// 則x一定是黑色,因此用x替代y不可能使兩個紅結點相鄰。
// 3.如果y是紅色,就不可能是根節點,所以根節點仍舊是黑色。
///////////////////////////////////////////////////////////////////////////////////////////
static RB_NODE* RbDelete(RB_NODE* head, RB_NODE* z)
{
RB_NODE* y = z;
RB_NODE* x;
COLOR yOrgClr = y->color;
if(z->left == NULL)
{
x = z->right;
head = RbTransplant(head,z,z->right);
}
else if(z->right == NULL)
{
x = z->left;
head = RbTransplant(head,z,z->left);
}
else
{
y = TreeMinmum(z->right);
yOrgClr = y->color;
x = y->right;
if(y->p == z)
{
if(x)
x->p = y; //如果後繼是其子
}
else //如果後繼是其孫輩或孫輩的後輩
{
head = RbTransplant(head,y,y->right);
y->right = z->right;
y->right->p = y;
}
head = RbTransplant(head,z,y);
y->left = z->left;
if(y->left)
{
y->left->p = y;
}
y->color = z->color;//替換之後,顏色復原
}
free(z);
if(yOrgClr == BLACK)
{
head = RbDeleteFixup(head,x);
}
return head;
}
//
//
static RB_NODE* RbDeleteFixup(RB_NODE* head, RB_NODE* x)
{
while(x && x->p != NULL && x->color == BLACK)
{
RB_NODE* w;
if(x == x->p->left) //
{
w = x->p->right;
if(w->color == RED)
{
w->color = BLACK;
x->p->color = RED;
head = LeftRotate(head,x->p);
w = x->p->right;
}
if(w->left->color == BLACK && w->right->color == BLACK)
{
w->color = RED;
x = x->p;
}
else
{
if(w->right->color)
{
w->left->color = BLACK;
w->color = RED;
head = RightRotate(head,w);
w = x->p->right;
}
w->color = x->p->color;
x->p->color = BLACK;
w->right->color = BLACK;
head = LeftRotate(head,x->p);
x = head;
}
}
else
{
w = x->p->left;
if(w->color == RED)
{
w->color = BLACK;
x->p->color = RED;
head = RightRotate(head,x->p);
w = x->p->left;
}
if(w->right->color == BLACK && w->left->color == BLACK)
{
w->color = RED;
x = x->p;
}
else
{
if(w->left->color)
{
w->right->color = BLACK;
w->color = RED;
head = LeftRotate(head,w);
w = x->p->left;
}
w->color = x->p->color;
x->p->color = BLACK;
w->left->color = BLACK;
head = RightRotate(head,x->p);
x = head;
}
}
}
if(x)
x->color = BLACK;
return head;
}
static void TreePrint(RB_NODE* node)
{
if(node == NULL)
{
return ;
}
//printf("<%c>",node->data);//先序遍歷p,l,r
TreePrint(node->left);
printf("<%d>",node->key);// 中序遍歷l,p,r
TreePrint(node->right);
//printf("<%c>",node->data);//後序遍歷
}
//RBTree.h
#ifndef RB_TREE_H
#define RB_TREE_H
#include "common.h"
//302419016
typedef enum{RED,BLACK}COLOR;
typedef struct RB_NODE{
struct RB_NODE *left,*right,*p;
int key;
COLOR color;
}RB_NODE,*RB_TREE;
void RBTree();
#endif