红黑树操作
实验目的
通过插入操作建立一个红黑树,输入为1…n的数,同时将每次插入后的树信息打印出来。
实验原理
红黑树是一棵二叉搜索树,它在每个结点上增加了一个存储位来表示结点的颜色,可以是RED或BLACK。通过对任何一条从根到叶子的简单路径上各个结点的颜色约束,红黑树确保没有一条路径比其他路径长出2倍,因而是近似于平衡的。
树中每个结点有五个属性:color,key,left,right和p;通过添加哨兵(T_nil)对红黑树的边界进行限定。
一棵红黑树是满足下面红黑性质的二叉搜索树:
(1)每个结点或是红色,或是黑色的;
(2)根节点是黑色的;
(3)每个叶节点(NIL)是黑色的;
(4)如果一个结点是红色的,则它的两个子节点都是黑色的;
(5)对每个结点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色结点;
实验过程
旋转操作:左旋和右旋
LEFT-ROTATE(T, x)
1 y = x.right
2 x.right = y.left
3 if y.left !=T.nil
4 y.left.p = x
5 y.p = x.p
6 if x.p == T.nil
7 T.root = y
8 elseif x ==x.p.left
9 x.p.left = y
10 else x.p.right= y
11 y.left = x
12 x.p = y
RIGHT-ROTATE(T, x)
1 y = x.left
2 x.left = y.right
3 if y.right !=T.nil
4 y.right.p = x
5 y.p = x.p
6 if x.p == T.nil
7 T.root = y
8 elseif x ==x.p.right
9 x.p.right = y
10 else x.p.left =y
11 y.right = x
12 x.p = y
插入操作:插入一个新节点就像在二叉树中插入一个结点一样,但是由于红黑树多了一个颜色属性,因此初始插入的结点的颜色属性为RED。选择将插入结点的颜色属性初始为RED的原因:在红黑树中插入一个结点时,如果初始插入结点的颜色为BLACK时,那么将会破坏性质(5),而且在修改性质(5)的过程中,需要去遍历每条路径,显然这是低效率的;如果将颜色初始为RED时,那么将会破坏性质(2)和性质(4),性质(2)修改很简单,性质(4)的修改过程只需要考虑叔叔结点的颜色,就可以逐步实现;显然在通过将插入结点初始为RED是更高效的操作。
RB-INSERT(T, z)
1 y = T.nil
2 x = T.root
3 while x != T.nil
4 y = x
5 if z.key < x.key
6 x = x.left
7 else x = x.right
8 z.p = y
9 if y == T.nil
10 T.root = z
11 elseif z.key< y.key
12 y.left = z
13 else y.right =z
14 z.left = T.nil
15 z.right = T.nil
16 z.color = RED
17RB-INSERT-FIXUP(T, z)
RB-INSERT-FIXUP(T,z)
1 while z.p.color== RED
2 if z.p == z.p.p.left
3 y = z.p.p.right
4 if y.color == RED
5 z.p.color = BLACK
6 y.color = BLACK
7 z.p.p.color = RED
8 z = z.p.p
9 else if z == z.p.right
10 z = z.p
11 LEFT-ROTATE(T, z)
12 else
13 z.p.color = BLACK
14 z.p.p.color = RED
15 RIGHT-ROTATE(T, z.p.p)
16 else(same as then clause with “right” and“left” exchanged)
17 T.root.color = BLACK
实验总结
(一)在实验过程中,输入是通过调用一个struct node * creat_node(tree_pointerT, int key)来实现的,但是这种方法存在一个问题:使用malloc分配内存时,在最后没有进行free处理,容易造成内存泄漏;
(二)关于树的打印,实验主要关注的是红黑树算法代码的实现,所以没有过于的去关注数的可视性。说明一下如何理解打印下来的树,右端最突出的是根节点,下端是左子树,上端是右子树;,
(三)在整个实验过程中,由于自己基础较差,可能附录的代码中有多处注释,想了想还是没有删掉,也是一种实现算法的过程,以及如何去调试程序吧。
附录(代码)
#include <stdio.h>
#include <stdlib.h>
typedef structnode *tree_pointer;
typedef struct node {
int key;
char color; //R represents red; B represents black
tree_pointerp;
tree_pointerleft;
tree_pointerright;
} *tree_pointer;
void RB_insert(tree_pointer T_nil, tree_pointerT_root, tree_pointer z);
void left_rotate(tree_pointer T_nil, tree_pointerT_root, tree_pointer x);
void right_rotate(tree_pointer T_nil, tree_pointerT_root, tree_pointer x);
void RB_insert_fixup(tree_pointer T_nil, tree_pointerT_root, tree_pointer z);
void print_tree(tree_pointer T_root, int n);
int get_tree_height(tree_pointer T_root);
struct node * creat_node(tree_pointer T, int key);
int main(){
inti,num,key,tree_height;
tree_pointernew_node = NULL;
tree_pointerT_root = NULL;
tree_pointerT_nil = NULL;
T_nil =(struct node *)malloc(sizeof(struct node));
T_nil->color= 'B';
T_root =(struct node *)malloc(sizeof(struct node));
// T_root->key = 11;
T_root->color= 'B';
T_root->p = T_nil;
T_root->left = T_nil;
T_root->right= T_nil;
printf("T_nil= %p; key = %d; color = %c; p = %p; left = %p; right = %p\n",T_nil,T_nil->key, T_nil->color, T_nil->p, T_nil->left, T_nil->right);
printf("T_root= %p; key = %d; color = %c; p = %p; left = %p; right = %p\n",T_root,T_root->key, T_root->color, T_root->p, T_root->left,T_root->right);
printf("pleaseinput the number of nodes:");
scanf("%d",&num);
printf("pleaseinput the key:");
scanf("%d",&key);
T_root->key= key;
printf("\n");
tree_height =get_tree_height(T_root);
print_tree(T_root,tree_height);
printf("\n");
for(i = 0; i< num-1; i++){
printf("pleaseinput the key:");
scanf("%d",&key);
printf("\n");
new_node =creat_node(T_nil, key);
RB_insert(T_nil,T_root, new_node);
// tree_height= get_tree_height(T_root);
// print_tree(T_root,tree_height);
// printf("\n666666666666666666666666\n");
}
/*
tree_pointernew1 = NULL;
tree_pointernew2 = NULL;
tree_pointernew3 = NULL;
tree_pointernew4 = NULL;
tree_pointernew5 = NULL;
// T_root =creat_node(T_nil, 11);
new1 =creat_node(T_nil, 2);
new2 =creat_node(T_nil, 14);
new3 =creat_node(T_nil, 1);
new4 =creat_node(T_nil, 7);
new5 =creat_node(T_nil, 15);
RB_insert(T_nil,T_root, new1);
RB_insert(T_nil,T_root, new2);
RB_insert(T_nil,T_root, new3);
RB_insert(T_nil,T_root, new4);
RB_insert(T_nil,T_root, new5);
printf("%p, %p %p",new1->p,new1->left,new1->right);
new1 = new2;
printf("\n1111111111111111111111111\n");
printf("new1= %p; key = %d; color = %c;",new1,new1->key,new1->color);
printf("p=%p; left = %p; right = %p\n",new1->p,new1->left,new1->right);
printf("new2= %p; key = %d; color = %c; p = %p; left = %p; right = %p\n",new2,new2->key, new2->color, new2->p, new2->left, new2->right);
*/
// tree_height =get_tree_height(T_root);
// print_tree(T_root,tree_height);
}
struct node * creat_node(tree_pointer T, int key){
tree_pointernew = NULL;
new = (structnode *)malloc(sizeof(struct node));
new->key = key;
new->color= 'R';
new->p = T;
new->left = T;
new->right= T;
return new;
}
void RB_insert(tree_pointer T_nil, tree_pointerT_root, tree_pointer z){
tree_pointerx = NULL;
tree_pointery = NULL;
y = T_nil;
x = T_root;
// printf("\nnowRB_insert is running!\n");
while(x !=T_nil){
y = x;
if(z->key< x->key)
x =x->left;
else
x =x->right;
}
z->p = y;
if(y ==T_nil)
T_root = z;
elseif(z->key < y->key)
y->left = z;
else
y->right= z;
z->left = T_nil;
z->right =T_nil;
z->color ='R';
RB_insert_fixup(T_nil,T_root, z);
// printf("\nnowRB_insert is over!\n");
}
void RB_insert_fixup(tree_pointer T_nil, tree_pointerT_root, tree_pointer z){
tree_pointery = NULL;
// printf("\nnowRB_insert_fixup is running!\n");
while(z->p->color== 'R'){
if(z->p== z->p->p->left){
y =z->p->p->right;
if(y->color== 'R'){
z->p->color = 'B';
y->color = 'B';
z->p->p->color= 'R';
z =z->p->p;
}
elseif(z == z->p->right){
z =z->p;
left_rotate(T_nil,T_root, z);
}
else{
z->p->color = 'B';
z->p->p->color= 'R';
right_rotate(T_nil,T_root, z->p->p);
}
}
//
elseif(z->p = z->p->p->right){
y =z->p->p->left;
if(y->color== 'R'){
z->p->color = 'B';
y->color = 'B';
z->p->p->color= 'R';
z =z->p->p;
}
elseif(z == z->p->left){
z =z->p;
right_rotate(T_nil,T_root, z);
}
else{
z->p->color = 'B';
z->p->p->color= 'R';
left_rotate(T_nil,T_root, z->p->p);
}
}
T_root->color= 'B';
}
// printf("\nnowRB_insert_fixup is over!\n");
inttree_height;
if(T_root->p== T_nil){
tree_height= get_tree_height(T_root);
print_tree(T_root,tree_height);
}
else{
tree_height= get_tree_height(T_root);
print_tree(T_root->p,tree_height);
}
}
void left_rotate(tree_pointer T_nil, tree_pointerT_root, tree_pointer x){
tree_pointery = NULL;
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;
}
void right_rotate(tree_pointer T_nil, tree_pointerT_root, tree_pointer x){
tree_pointery = NULL;
y =x->left;
x->left =y->right;
if(y->right!= T_nil)
y->right->p= x;
y->p =x->p;
if(x->p ==T_nil)
T_root =y;
else if(x ==x->p->right)
x->p->right= y;
else
x->p->left= y;
y->right =x;
x->p = y;
}
int get_tree_height(tree_pointer T_root){
if(!T_root)
return 0;
intleft_height,right_height;
left_height = get_tree_height(T_root->left);
right_height= get_tree_height(T_root->right);
return(left_height < right_height)?(right_height+1):(left_height+1);
}
void print_tree(tree_pointer T_root, int n){
int i;
if(T_root ==NULL)
return;
print_tree(T_root->right, n-1);
for(i = 0; i< n-1; i++)
printf(" ");
if(n > 0){
printf("---");
printf("%d(%c)\n",T_root->key,T_root->color);
}
print_tree(T_root->left,n-1);
}