观察红黑树的四种情况
根据红黑树的五条性质:
- 节点为红色或黑色
- 根是黑色
- 叶子节点(外部节点,空节点)为黑色
- 红节点的子节点为黑色,红节点的父节点为黑色,根节点到叶子节点的所有路径不能有两个连续的红色节点
- 任意节点到叶子节点所有路径包含相同数目的红色节点
可以看到,如果把某一层的红色节点和上一层父节点合并成一个节点,就变成了一个满足如下条件的四阶B树:
- 红黑树黑色节点数与4阶B树节点总数相等
- 所有B树节点,黑节点永远是父节点,红节点是子节点,黑节点在中间,红节点在两边
由这四种B树节点类型,插入节点情况分为三个大类:
- 插入节点后元素数超过3个,向上溢出(存在uncle节点且为红的情况,不涉及左右旋,只涉及颜色的调整和B树结点的分裂,同时将上溢的祖父节点当作新插入节点插入上一层判断)
- 插入节点父节点为黑(插入节点为红色节点,直接插入满足红黑树性质,不做调整)
- 插入节点父节点为红(uncle节点或不存在,或存在且为黑)
由此来实现我们的代码:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef enum{
RED,
BLACK
}Color;
typedef struct RBTreeNode{
struct RBTreeNode* _left;
struct RBTreeNode* _right;
struct RBTreeNode* _parent;
int data;
Color _col;
}RBTreeNode;
RBTreeNode* createRBTreeNode(int data){
RBTreeNode* node =(RBTreeNode*)malloc(sizeof(RBTreeNode));
if(!node){
fprintf(stderr, "Memory allocation failed\n");
exit(EXIT_FAILURE);
}
node->_left = NULL;
node->_right=NULL;
node->_parent=NULL;
node->data=data;
node->_col=RED;
return node;
}
RBTreeNode* search(RBTreeNode* T,int key){
while(T!=NULL&&key!=T->data){
if(key<T->data){
T=T->_left;
}
else
T=T->_right;
}
return T;
}
void RotateL(RBTreeNode* parent,RBTreeNode* T){/左旋操作,重点是将该节点右孩子的左孩子变为该节点的右孩子,该节点变为右孩子的左孩子
RBTreeNode* subR=parent->_right;
RBTreeNode* subRL=subR->_left;
parent->_right=subRL;
if(subRL){
subRL->_parent=parent;
}
RBTreeNode* grand=parent->_parent;
subR->_left=parent;
parent->_parent=subR;
if(grand==NULL){
T=subR;
T->_parent=NULL;
}
else{
if(grand->_left==parent){
grand->_left=subR;
}
else{
grand->_right=subR;
}
subR->_parent=grand;
}
}
void RotateR(RBTreeNode* parent,RBTreeNode* T){//右旋操作,与左旋操作轴对称
RBTreeNode* subL=parent->_left;
RBTreeNode* subLR=subL->_right;
parent->_left=subLR;
if(subLR){
subLR->_parent=parent;
}
RBTreeNode* grand=parent->_parent;
subL->_right=parent;
parent->_parent=subL;
if(grand==NULL){
T=subL;
T->_parent=NULL;
}
else{
if(grand->_left==parent){
grand->_left=subL;
}
else{
grand->_right=subL;
}
subL->_parent=grand;
}
}
bool insert(RBTreeNode** T,int data){//指向指针的指针
RBTreeNode* cur = createRBTreeNode(data);
if (*T == NULL) {
*T = cur;
(*T)->_col = BLACK; // 第一个节点通常是黑色的
return true;
}
RBTreeNode* parent = NULL;
RBTreeNode* current = *T;
while(current){
if(current->data<data){
parent =current;
current=current->_right;
}
else if(current->data>data){
parent=current;
current=current->_left;
}
else{
return false;
}
}//遍历获取插入节点的parent
if(parent->data>data){
parent->_left=cur;
}
else{
parent->_right=cur;
}
cur->_parent = parent; //将插入节点的parent指向真正的parent
while(parent &&parent->_col==RED){
RBTreeNode* grand=parent->_parent;
if(grand->_left==parent){
RBTreeNode* uncle=grand->_right;
//1:u存在且为红,变色,向上溢出
if(uncle&&uncle->_col==RED){
parent->_col=BLACK;
uncle->_col=BLACK;
grand->_col=RED;
//向上溢出
cur=grand;
parent=cur->_parent;
}
else{
// g
// p u
// c
if(cur==parent->_left){
RotateR(grand,(*T));
parent->_col=BLACK;
grand->_col=RED;
}
else{
// g
// p u
// c
RotateL(parent,(*T));
RotateR(grand,(*T));
cur->_col=BLACK;
grand->_col=RED;
}
break;
}
}
else{// (grandfather->_right == parent)
RBTreeNode* uncle=grand->_left;
if(uncle&&uncle->_col==RED){
parent->_col=BLACK;
uncle->_col=BLACK;
grand->_col=RED;
//向上溢出
cur=grand;
parent=grand->_parent;
}
else{
// g
// u p
// c
if(cur==parent->_right){
RotateL(grand,(*T));
grand->_col=RED;
parent->_col=BLACK;
}
else{
// g
// u p
// c
RotateR(parent,(*T));
RotateL(grand,(*T));
grand->_col=RED;
cur->_col=BLACK;
}
break;
}
}
}
printf("%d\n",cur->data);
(*T)->_col=BLACK;
return true;
}
void inorderTraversal(RBTreeNode* root) { //中序遍历红黑树
if (root != NULL) {
inorderTraversal(root->_left);
printf("%d(%s) ", root->data, root->_col == RED ? "RED" : "BLACK");
inorderTraversal(root->_right);
}
}
int main() {
RBTreeNode* root = NULL;
bool flag=true;
int num[]={7,3,18,10,22,8,11,26};
for(int i=0;i<8;i++){
if(!flag){
break;
}
flag=insert(&root,num[i]);
}
printf("Inorder Traversal of the created RBTree is \n");
inorderTraversal(root);
printf("\n");
return 0;
}