本部分主要是进行红黑树插入操作的代码实现与部分图片解释:
上一部分解释一些关于红黑树的插入操作和旋转染色的操作,忘记了的小伙伴么可以再温习一下,
下面开始coding。。。。
左旋操作--->代码如下:
void left_rotate(node *tree_root,node *z){
node * y ;
//将Z的右子树赋值给y由y来管理
y = z->right;
//将z的右侧指向y的侧树的节点
z->right = y->left;
if(y->left != NULL){//如果y的左子树不为空,那么将y的左子树的父指针指向z
y->left->parent = z;
}
//将y的父指针指向原来z的父指针指向的地方
y->parent = z->parent;
//如果z的父指针指的是空
if(z->parent == NULL){
tree_root = y;//那么z为树的根,更新一下树根的指针
}else if(z == z->parent->left){//如果z不是树根,是一个节点的左子树
z->parent->left = y;//则将z父节点的左侧指向y
}else{
z->parent->right = y;//否则将z父节点的右侧指向y
}
y->left = z;//最后将y替换z的位置,将y的左指针指向z
z->parent = y;//z的父指针指向y
}
进行左旋转时,传入进来的是树的根和要左移动的节点z,所以得根据z来找到z右侧的节点来做左旋转来代替z原来的位置,所以会有 y = z->right 来找到这个节点,然后将找到的右侧节点y的左侧子树变更到z的右侧子树处(因为原来z右侧的值一定是比Z值大的所以肯定是放在Z的右侧的,这个是二叉搜索树的性质,也是红黑树的性质)。变更之后然后再将Y节点的左侧指针指向Z,Y的父指针修改成原来Z的父指针指向的地方,因为Y要替换Z的位置。然后判断一下Z的父节点是否存在,如果不存在则说明Z为根节点,则修改一下树根的指针。如果z原来父节点存在,判断一下原来Z在父节点的左侧还是右侧,将该父节点的左右指针修改指向Y节点,最后将Z放在Y节点的左侧,将z的父指针指向Y节点。
右旋转操作--->代码如下:
void right_rotate(node *tree_root,node *z){
node *y;
y= z->parent;//找到z进行右旋转要替换的位置
y->left = z->right;//将y的左侧子树指向z原来的右子树
if(z->right!=NULL){
z->right->parent = y;
}
//修改z的父指针,因为z要替换y的位置
z->parent = y->parent;
if(y->parent ==NULL){//与左循环一样,判断这个父节点是否为树的根
tree_root = z;
}else if(y == y->parent->left){//判读一下z替换y之后再y节点的什么位置
y->parent->left = z;//左侧的情况
}else{
y->parent->right = z;//右侧的情况
}
z->right = y;//最后将z的右侧子树指向y
y->parent = z;//将y的父指针指向z
}
跟左旋转一样,右旋转也要找到其要替换的位置,本右侧旋转要找指定节点的父亲节点位置,所以又 y = z->parent ,找到之后先把z的右侧子树赋值给Y节点的左侧,道理同左旋转(二叉搜索树的性质),然后判断一下z的右侧子树是否为空,为空就不做任何处理,否则修改一下这个右子树的父指针,将其指向Z节点。之后将修改Z的父指针替换Y的父指针。然后判断这个Z是在原Y父节点的左侧还是右侧,最后将z的右指针指向Y,Y的父指针指向Z。
下面Coding红黑树的插入操作:
#define RED 0
#define BLACK 1
typedef struct node{
int key;
node *left;
node *right;
node *parent;
int color;
} node;
void RB_insert(node * tree_root,node *z){
node *y ,*x;
x= tree_root;
y = NULL;
//该while循环是为了找到Z应该插值的地方
while(x!=NULL){
y=x;
if(z->key < y->key){//如果Z的值比Y的值小,则向树的左侧搜索Z的位置
y = y->left;
}else{
y = y->right;//如果Z的值比Y的值大,则向树的右侧搜素Z的位置
}
}
//搜索到了Z的位置之后,将Z的父亲指针指向Y的位置
z->parent = y;
//然后随Z是在Y的左侧还是右侧进行判断。
if(y->parent==NULL){
tree_root = z;
}else if(z->key < y->key){
y->left = z;
}else{
y->right = z;
}
//最后将Z的左右节点赋值成守卫,并且初始化z的颜色为红色
z->left = NULL;
z->right =NULL;
z->color = RED;
RB_fixup(tree_root,z);
}
void RB_fixup(node *tree_root,node *z){
node *y;
while(z->color ==RED){
if(z->parent==z->parent->parent->left){
y = z->parent->parent->right;
if(y==RED){
z->parent->color = BLACK;//case1
y->color = BLACK; //case1
z->parent->parent = RED; //case1
z = z->parent->parent; //case1
}else if(z==z->parent->right){
z = z->parent; //case2
left_rotate(tree_root,z);//case2
}
z->parent->color =BLACK; //case3
z->parent->parent=RED; //case3
right_rotate(tree_root,z); //case3
}else if(z->parent==z->parent->parent->right){
y=z->parent->parent->left;
if(y==RED){
z->parent->color = BLACK;
y->color =BLACK;
z->parent->parent->color =RED;
z= z->parent->parent;
}else if(z == z->parent->left){
z = z->parent;
right_rotate(tree_root,z);
}
z->parent->color = BLACK;
z->parent->parent->color=RED;
left_rotate(tree_root,z);
}
}
tree_root->color =BLACK;
}