插入操作可能会造成不平衡。
为了使数平衡,AVL树需要rotate操作。那么红黑树怎么弄呢?红黑树需要:
1)recoloring
2) rotate
下面举例说明
假设x是新插入的节点。
1)标准BST树出入,插入后新节点上色为红
2)如果x不为root或者x的父节点不是黑的
a)如果x的叔节点为红:
1.变父节点和叔节点的颜色为黑
2.变爷节点颜色为红
3.爷节点变为新出入的当前结点
b)如果叔节点是黑色的,那么按照AVL树的四种旋转情况rotate
3)如果x为root,将x的颜色变为黑
下面具体讨论叔节点为黑色时候那四种旋转:
Left Left Case:
Left Right Case
Right Right Case
Right Left Case
插入实例:插入10,20,30,15
下面是C语言实现代码:
#include <stdio.h>
struct node
{
int data;// for data part
char color;// for color property
struct node* left;
struct node* right;
struct node* parent;
};
// leftrotate
void leftRotate(struct node** root,struct node* x)
{
// y store the x's right child
struct node* y=x->right;
// update x's righit child
x->right=y->left;
if(x->right!=NULL)
{
x->right->parent=x;
}
// update y's parent pointer
y->parent=x->parent;
// if x's parent is null,make y as root of tree
if(x->parent==NULL)
{
(*root)=y;
}
else if(x==x->parent->left)
{
x->parent->left=y;
}
else
{
x->parent->right=y;
}
y->left=x;
x->parent=y;
}
// similar to leftrotate
void rightRotae(struct node** root,struct node* x)
{
struct node* y=x->left;
x->left=y->right;
if(x->left!=NULL)
{
x->left->parent=x;
}
y->parent=x->parent;
if(x->parent=NULL)
{
(*root)=y;
}
else if(x=x->parent->left)
{
x->parent->left=y;
}
else
{
x->parent->right=y;
}
y->right=x;
x->parent=y;
}
void insertFixup(struct node** root,struct node* z)
{
while(z!=*root || z->parent->color=='R')
{
struct node* y;
// find uncle and stroe uncle in y
if(z->parent=z->parent->parent->left)
y=z->parent->parent->right;
else
y=z->parent->parent->left;
// if uncle is red,do following
// 1) change color of parent and uncle as black
// 2) change color of grandparent as red
// 3) move z to grandparent
if(y->color=='R')
{
y->color='B';
z->parent->color='B';
z->parent->parent='R';
z=z->parent->parent;
}
// uncle is black there is four case
else
{
// left left case do following
// 1) swap color parent and grandparent
// 2) right rotete grandparent
if(z=z->parent->left && z->parent=z->parent->parent->left)
{
char t=z->parent->color;
z->parent->color=z->parent->parent->color;
z->parent->parent->color=t;
rightRotae(root,z->parent->parent);
}
// left right case do following
// 1) swap color of current and grandparent
// 2) left rotate parent
// 3) right rotate grandparent
if(z=z->parent->right && z->parent=z->parent->parent->left)
{
char t=z->color;
z->color=z->parent->parent->color;
z->parent->parent->color=t;
leftRotate(root,z->parent);
rightRotae(root,z->parent->parent);
}
// right right case do following
// 1) swap color of parent and grandparent
// 2) left rotate grandparent
if(z=z->parent->right && z->parent=z->parent->parent->right)
{
\char t=z->parent->color;
z->parent->color=z->parent->parent->color;
z->parent->parent->color=t;
leftRotate(root,z->parent->parent);
}
// right left case do following
// 1) swap color of current and grandparent
// 2) right rotate parent
// 3) left rotate grandparent
if(z=z->parent->left && z->parent=z->parent->parent->right)
{
char t=z->color;
z->color=z->parent->parent->color;
z->parent->parent->color=t;
rightRotae(root,z->parent);
leftRotate(root,z->parent->parent);
}
}
}
(*root)->color='B';// keep root always black
}
void insert(struct node** root,int data)
{
// allocate memory for new node
struct node* z=(struct node*)malloc(sizeof(struct node));
z->data=data;
z->left=z->right=z->parent=NULL;
// if root is null make z as root
if(root==NULL)
{
z->color='B';
(*root)=z;
}
else
{
struct node* pre=NULL;
struct node* p=(*root);
while(p)
{
pre=p;
if(z->data>p->data)
p=p->right;
else
p=p->left;
}
z->parent=pre;
if(z->data>pre->data)
pre->right=z;
else
pre->left=z;
z->color='R';
insertFixup(root,z);
}
}
void inorder(struct node* root)
{
if(root==NULL)
return;
inorder(root->left);
printf("%d ",root->data);
inorder(root->right);
}
int main(void)
{
struct node* root=NULL;
insert(&root,5);
insert(&root,3);
insert(&root,7);
insert(&root,2);
insert(&root,4);
insert(&root,6);
insert(&root,8);
insert(&root,11);
inorder(root);
printf("Hello World!\n");
return 0;
}