#include <iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
#define RED 0 //红色用数字0表示
#define BLACK 1 //黑色用数字1表示
#define COLOR(x) ((x)->color)//获取x节点颜色
#define PARENTNODE(x) ((x)->parentNode)//获取x节点的父节点
#define SET_PARENT(x,p) ((x)->parentNode=(p)) //设置x节点的父节点
#define SET_COLOR(x,c) ((x)->color=(c))//设置x节点的颜色
#define SET_BLACK(x) ((x)->color=BLACK) //将x节点的颜色置为黑色
#define SET_RED(x) ((x)->color=RED) //将x节点的颜色置为红色
#define IS_BLACK(x) ((x)->color==BLACK)//判断x节点的颜色是否为黑色
#define IS_RED(x) ((x)->color==RED) //判断x节点的颜色是否为红色
typedef struct RBTNode
{
int color;//红黑树的节点颜色
int key;//红黑树节点的值
struct RBTNode* parentNode;//父节点
struct RBTNode* lChild;//左孩子
struct RBTNode* rChild;//右孩子
} Node; //定义红黑树结点
typedef struct RBTree
{
Node* root;//根节点
int treeSize;//树的大小
} RBTree;
Node* createNode(int data);//创建红黑树节点
void leftRotation(RBTree* tree,Node* x);//将x节点左旋
void rightRotation(RBTree* tree,Node* y);//将y节点右旋
void traversePreorder(Node* root);//先序遍历红黑树
void traverseInorder(Node* root);//中序遍历红黑树
RBTree* createBbtree();//创建一棵红黑树
void adjustNode(RBTree* tree,Node* node);//调整结点
void insertRbtree(RBTree* tree,Node* node);//插入节点
Node* searchNode(Node* root,int key);//查找节点
void adjustDelete(RBTree* tree,Node* node,Node* parent); //调整删除节点
void deleteNode(RBTree* tree,Node* node);//删除节点
void deleteRbtree(RBTree* tree,int key);//根据已知数值删除节点
int main()
{
int arr[9]= {10,40,30,60,90,70,20,50,80};
int length=9;
RBTree* tree=createBbtree();//创建一棵红黑树
for(int i=0; i<length; i++)
{
insertRbtree(tree,createNode(arr[i]));//往红黑树中插入节点
}
printf("先序遍历结果如下:\n");
traversePreorder(tree->root);//先序遍历红黑树
printf("--------------------\n");
printf("中序遍历的结果如下:\n");
traverseInorder(tree->root);//中序遍历红黑树
printf("--------------------\n");
deleteRbtree(tree,80);//删除80
printf("先序遍历结果如下:\n");
traversePreorder(tree->root);//先序遍历红黑树
printf("--------------------\n");
printf("中序遍历的结果如下:\n");
traverseInorder(tree->root);//中序遍历红黑树
printf("--------------------\n");
return 0;
}
Node* createNode(int data)//创建红黑树节点
{
Node* newNode=new Node;
newNode->color=BLACK;//把新节点的颜色置为黑色
newNode->key=data;
//初始化节点
//将父节点和左右孩子节点均置为空
newNode->parentNode=NULL;
newNode->lChild=NULL;
newNode->rChild=NULL;
return newNode;//返回新创建的节点
}
void leftRotation(RBTree* tree,Node* x)//将x节点左旋
{
Node* y=x->rChild;
x->rChild=y->lChild;
if(y->lChild!=NULL)
{
y->lChild->parentNode=x;
}
y->parentNode=x->parentNode;
if(x->parentNode==NULL)//判断x节点是否为根节点
{
tree->root=y;
}
else if(x->parentNode->lChild==x)//判断x是否为左子树
{
x->parentNode->lChild=y;
}
else
{
x->parentNode->rChild=y;
}
y->lChild=x;
x->parentNode=y;
}
void rightRotation(RBTree* tree,Node* y)//将y节点右旋
{
Node* x=y->lChild;
y->lChild=x->rChild;
if(x->rChild!=NULL)
{
x->rChild->parentNode=y;
}
x->parentNode=y->parentNode;
if(y->parentNode==NULL)//判断y节点是否为根节点
{
tree->root=x;
}
else if(y==y->parentNode->lChild)
{
y->parentNode->lChild=x;
}
else
{
y->parentNode->rChild=x;
}
x->rChild=y;
y->parentNode=x;
}
void traversePreorder(Node* root)//先序遍历红黑树
{
if(root!=NULL)//判断该树是否为空
{
//打印节点的值和颜色
printf("%d---%s\n",root->key,root->color?"black":"red");
traversePreorder(root->lChild);
traversePreorder(root->rChild);
}
}
void traverseInorder(Node* root)//中序遍历红黑树
{
if(root!=NULL)
{
traverseInorder(root->lChild);
printf("%d---%s\n",root->key,root->color?"black":"red");
traverseInorder(root->rChild);
}
}
RBTree* createBbtree()//创建一棵红黑树
{
RBTree* tree=new RBTree;
tree->root=NULL;//将树的根节点初始化为空
tree->treeSize=0;//将树的大小初始化为0
return tree;
}
void adjustNode(RBTree* tree,Node* node)//调整节点
{
Node* parent,*Gparent;
while((parent=PARENTNODE(node))&&IS_RED(parent))//判断父节点是否非空且颜色是否是红色
{
Gparent=PARENTNODE(parent);//获取祖父节点
if(parent==Gparent->lChild)//父节点是祖父节点的左孩子
{
//情况一:叔叔节点是红色
Node* uncle=Gparent->rChild;
if(uncle && IS_RED(uncle))
{
SET_BLACK(uncle);//将叔叔节点设置为黑色
SET_BLACK(parent);//将父节点设置为黑色
SET_RED(Gparent);//将祖父节点设置为红色
node=Gparent;
continue;
}
//情况二:叔叔节点是黑色,当前节点是右孩子
else if(parent->rChild==node)
{
leftRotation(tree,parent);
Node* temp=parent;
parent=node;
node=temp;
}
else
{
//情况三:叔叔节点是黑色,当前节点是左孩子
SET_BLACK(parent);//将父节点设置为黑色
SET_RED(Gparent);//将祖父节点设置为红色
rightRotation(tree,Gparent);
}
}
else
{
//情况一:叔叔节点是红色
Node* uncle=Gparent->lChild;
if(uncle && IS_RED(uncle))
{
SET_BLACK(uncle);//将叔叔节点设置为黑色
SET_BLACK(parent);//将父节点设置为黑色
SET_RED(Gparent);//将祖父节点设置为红色
node=Gparent;
continue;
}
//情况二:叔叔节点是黑色,当前节点是右孩子
else if(parent->lChild==node)
{
rightRotation(tree,parent);
Node* temp=parent;
parent=node;
node=temp;
}
else
{
//情况三:叔叔节点是黑色,当前节点是左孩子
SET_BLACK(parent);//将父节点设置为黑色
SET_RED(Gparent);//将祖父节点设置为红色
leftRotation(tree,Gparent);
}
}
}
SET_BLACK(tree->root);//将根节点设置为黑色
}
void insertRbtree(RBTree* tree,Node* node)//插入节点
{
Node* preNode=NULL;//前驱节点
Node* curNode=tree->root;//将当前节点设置为根节点
while(curNode!=NULL)//判断当前节点是否为空
{
preNode=curNode;
if(node->key<curNode->key)
{
curNode=curNode->lChild;//插入节点的值小于当前节点的值就往左走
}
else
{
curNode=curNode->rChild;
}
}
SET_PARENT(node,preNode);//将插入节点的父节点设置为前驱节点
if(preNode!=NULL)//判断前驱节点是否为空
{
if(preNode->key>node->key)
{
preNode->lChild=node;
}
else
{
preNode->rChild=node;
}
}
else
{
tree->root=node;//若前驱节点为空,说明插入节点是根节点
}
SET_COLOR(node,RED);//将插入节点设置为红色
tree->treeSize++;//插入节点后树的大小加1
adjustNode(tree,node);//调整节点
}
Node* searchNode(Node* root,int key)//查找节点
{
if(root==NULL||root->key==key)
{
return root;
}
else if(key<root->key)
{
return searchNode(root->lChild,key);
}
else
{
return searchNode(root->rChild,key);
}
}
void adjustDelete(RBTree* tree,Node* node,Node* parent) //调整删除节点
{
Node* brother;//删除节点的兄弟节点
while(!node||(IS_BLACK(node)&&node!=tree->root))//当节点非空或节点为黑色节点且不是根节点时
{
if(parent->lChild==node)//删除节点是左孩子
{
brother=parent->rChild;
if(IS_RED(brother))
{
//第一种情况:兄弟节点是红色节点
SET_BLACK(brother);//将兄弟节点设置为黑色
SET_RED(parent);//把父节点设置为红色
leftRotation(tree,parent);//以父节点为支点作左旋操作
brother=parent->rChild;//将兄弟节点设置为左旋操作后的右孩子
}
if((!brother->lChild)&&(!brother->rChild))//判断兄弟节点是否为叶子节点
{
//第二种情况:兄弟节点是黑色的
SET_RED(brother);//将兄弟节点设置为红色
node=parent;//将当前节点设置为父节点
parent=PARENTNODE(node);
}
else
{
if((!brother->rChild)||IS_BLACK(brother->rChild))
{
//第三种情况:兄弟节点是黑色的,兄弟节点的左孩子是红色的,右孩子是黑色的
SET_BLACK(brother->lChild);//将兄弟节点的左孩子设置为黑色
SET_RED(brother);//将兄弟节点设置为红色
rightRotation(tree,brother);//以兄弟节点为支点进行右旋操作
brother=parent->rChild;//将兄弟节点设置为父节点的右孩子
}
else
{
SET_COLOR(brother,COLOR(parent));//将兄弟节点的颜色设置为父节点的颜色
SET_BLACK(parent);//将父节点设置为黑色
SET_BLACK(brother->rChild);//将兄弟节点的右孩子设置为黑色
leftRotation(tree,parent);//以父节点为支点作左旋操作
node=tree->root;//将删除节点设置为根节点
break;
}
}
}
else//删除节点是右孩子
{
brother=parent->lChild;
if(IS_RED(brother))
{
//第一种情况:兄弟节点是红色节点
SET_BLACK(brother);//将兄弟节点设置为黑色
SET_RED(parent);//把父节点设置为红色
leftRotation(tree,parent);//以父节点为支点作左旋操作
brother=parent->lChild;//将兄弟节点设置为左旋操作后的左孩子
}
if((!brother->lChild)&&(!brother->rChild))//判断兄弟节点是否为叶子节点
{
//第二种情况:兄弟节点是黑色的
SET_RED(brother);//将兄弟节点设置为红色
node=parent;//将当前节点设置为父节点
parent=PARENTNODE(node);
}
else
{
if((!brother->lChild)||IS_BLACK(brother->lChild))
{
//第三种情况:兄弟节点是黑色的,兄弟节点的左孩子是红色的,右孩子是黑色的
SET_BLACK(brother->rChild);//将兄弟节点的左孩子设置为黑色
SET_RED(brother);//将兄弟节点设置为红色
rightRotation(tree,brother);//以兄弟节点为支点进行右旋操作
brother=parent->lChild;//将兄弟节点设置为父节点的右孩子
}
else
{
//第四种情况
SET_COLOR(brother,COLOR(parent));//将兄弟节点的颜色设置为父节点的颜色
SET_BLACK(parent);//将父节点设置为黑色
SET_BLACK(brother->lChild);//将兄弟节点的右孩子设置为黑色
leftRotation(tree,parent);//以父节点为支点作左旋操作
node=tree->root;//将删除节点设置为根节点
break;
}
}
}
}
if(node)
{
SET_BLACK(node);//将节点颜色设置为黑色
}
}
void deleteNode(RBTree* tree,Node* node)//删除节点
{
Node* child,*parent;
int color;
if((node->lChild!=NULL)&&(node->rChild!=NULL))//判断左右子树是否均非空
{
Node* reNode=node;//reNode为替换节点
reNode=reNode->rChild;//右边找最左边替换
while(reNode->lChild!=NULL)
{
reNode=reNode->lChild;
}
if(PARENTNODE(node))//判断删除节点是否为根部
{
if(PARENTNODE(node)->lChild==node)//判断删除节点是否为左孩子
{
PARENTNODE(node)->lChild=reNode;//用替换节点替换删除节点的位置
}
else
{
PARENTNODE(node)->rChild=reNode;
}
}
else
{
tree->root=reNode;//将根节点设置为替换掉节点
}
child=reNode->rChild;
parent=PARENTNODE(reNode);
color=COLOR(reNode);
if(parent==node)
{
parent=reNode;
}
else
{
if(child)
{
SET_PARENT(child,parent);
}
parent->lChild=child;
reNode->rChild=node->rChild;
SET_PARENT(node->rChild,reNode);
}
//调整替换节点的父节点
reNode->parentNode=node->parentNode;
reNode->color=node->color;
reNode->lChild=node->lChild;
//调整删除节点的父节点
node->lChild->parentNode=reNode;
if(color==BLACK)//如果删除节点为黑色节点,则需要调整节点
{
adjustDelete(tree,child,parent);
}
free(node);//释放删除节点
node=NULL;
return ;
}
//考虑只有单边的情况
if(node->lChild!=NULL)//如果只有左孩子
{
child=node->lChild;
}
else//如果只有右孩子
{
child=node->rChild;
}
parent=node->parentNode;
color=node->color;
if(parent)//判断删除节点的父节点是否为空
{
if(parent->lChild==node)
{
parent->lChild=child;
}
else
{
parent->rChild=child;
}
}
else
{
tree->root=child;
}
if(color==BLACK)//如果删除节点颜色为黑色,需要进行调整
{
adjustDelete(tree,child,parent);
}
free(node);
node=NULL;
}
void deleteRbtree(RBTree* tree,int key)//根据已知数值删除节点
{
Node* result=searchNode(tree->root,key);//先查找要删除的节点
if(result!=NULL)
{
deleteNode(tree,result);
}
}