1. 基本概念
RBT的作用与平衡二叉树类似,目的是优化原始BST查找效率低的问题。RBT需成立,要满足如下条件:
- 树中每个节点有颜色(红或黑)
- 根节点必须为黑色
- NULL值处称为终端节点,我们可以认为是黑色
- 不允许两个红节点互为父子关系
- 从任意节点向下出发,到所有终端节点的各条路径上黑节点个数相同
2. RBT节点添加
向RBT添加节点,该节点默认初始化为红色。(若为黑色则第五个条件不满足,若为红色可能不满足第四个条件,但第五个条件不好调控,所以选择红色。)
添加步骤如下图:
3. RBT节点删除
代码实现:
#include<stdio.h>
#include<stdlib.h>
enum COLOR{RED,BLACK};
typedef struct rbt
{
int nValue;
int nColor;
struct rbt *pLeft;
struct rbt *pRight;
struct rbt *pFather;
}RBT;
RBT *pRBT = NULL;
void RightRotate(RBT **pTree)
{
if(*pTree == NULL || (*pTree)->pLeft == NULL)return;
RBT *pNode = *pTree;
RBT *pMark = pNode->pLeft;
//三个孩子关系
pNode->pLeft = pMark->pRight;
pMark->pRight = pNode;
if(pNode->pFather != NULL)
{
if(pNode == pNode->pFather->pLeft)
{
pNode->pFather->pLeft = pMark;
}
else
{
pNode->pFather->pRight = pMark;
}
}
else
{
//换根
pRBT = pMark;
}
//三个父亲关系
if(pNode->pLeft != NULL)
{
pNode->pLeft->pFather = pNode;
}
pMark->pFather = pNode->pFather;
pNode->pFather = pMark;
}
void LeftRotate(RBT **pTree)
{
if(*pTree == NULL || (*pTree)->pRight == NULL)return;
RBT *pNode = *pTree;
RBT *pMark = pNode->pRight;
//三个孩子关系
pNode->pRight = pMark->pLeft;
pMark->pLeft = pNode;
if(pNode->pFather != NULL)
{
if(pNode == pNode->pFather->pLeft)
{
pNode->pFather->pLeft = pMark;
}
else
{
pNode->pFather->pRight = pMark;
}
}
else
{
//换根
pRBT = pMark;
}
//三个父亲关系
if(pNode->pRight != NULL)
{
pNode->pRight->pFather = pNode;
}
pMark->pFather = pNode->pFather;
pNode->pFather = pMark;
}
RBT *Search(RBT *pTree,int nNum)
{
if(pTree == NULL)return NULL;
while(pTree)
{
if(pTree->nValue > nNum)
{
//左侧
if(pTree->pLeft == NULL)
{
return pTree;
}
pTree = pTree->pLeft;
}
else if(pTree->nValue < nNum)
{
if(pTree->pRight == NULL)
{
return pTree;
}
pTree = pTree->pRight;
}
else
{
printf("data error.\n");
exit(1);
}
}
}
RBT *GetUncle(RBT *pNode)
{
if(pNode == pNode->pFather->pLeft)
{
return pNode->pFather->pRight;
}
else
{
return pNode->pFather->pLeft;
}
}
void AddNode(RBT *pTree,int nNum)
{
//查找
RBT *pNode = NULL;
pNode = Search(pTree,nNum);
//申请空间
RBT *pTemp = NULL;
pTemp = (RBT*)malloc(sizeof(RBT));
pTemp->nValue = nNum;
pTemp->nColor = RED;
pTemp->pFather = pNode;
pTemp->pLeft = NULL;
pTemp->pRight = NULL;
//情况分析
//1.空树
if(pNode == NULL)
{
pRBT = pTemp;
pRBT->nColor = BLACK;
return;
}
//非空树
//连接
if(pTemp->nValue < pNode->nValue)
{
pNode->pLeft = pTemp;
}
else
{
pNode->pRight = pTemp;
}
//2.父亲是黑的
if(pNode->nColor == BLACK)
{
return;
}
//3.父亲是红的
RBT *pUncle = NULL;
RBT *pGrandFather = NULL;
while(pNode->nColor == RED)
{
pGrandFather = pNode->pFather;
pUncle = GetUncle(pNode);
//3.1叔叔是红色
if(pUncle != NULL && pUncle->nColor == RED)
{
pNode->nColor = BLACK;
pUncle->nColor = BLACK;
pGrandFather->nColor = RED;
pTemp = pGrandFather;
pNode = pTemp->pFather;
//根
if(pNode == NULL)
{
pRBT->nColor = BLACK;
break;
}
continue;
}
//3.2叔叔是黑的
if(pUncle == NULL || pUncle->nColor == BLACK)
{
//3.2.1父亲是爷爷的左
if(pNode == pGrandFather->pLeft)
{
//3.2.1.1当前节点是父亲的右
if(pTemp == pNode->pRight)
{
pTemp = pNode;
LeftRotate(&pTemp);
pNode = pTemp->pFather;
}
//3.2.1.2当前节点是父亲的左侧
if(pTemp == pNode->pLeft)
{
pNode->nColor = BLACK;
pGrandFather->nColor = RED;
RightRotate(&pGrandFather);
break;
}
}
//3.2.2父亲是爷爷的右
if(pNode == pGrandFather->pRight)
{
//3.2.2.1当前节点是父亲的左
if(pTemp == pNode->pLeft)
{
pTemp = pNode;
RightRotate(&pTemp);
pNode = pTemp->pFather;
}
//3.2.2.2当前节点是父亲的右
if(pTemp == pNode->pRight)
{
pNode->nColor = BLACK;
pGrandFather->nColor = RED;
LeftRotate(&pGrandFather);
break;
}
}
}
}
}
void CreateRBT(int arr[],int nLength)
{
if(arr == NULL || nLength <= 0)return;
int i;
for(i = 0;i<nLength;i++)
{
AddNode(pRBT,arr[i]);
}
}
void Traversal(RBT *pTree)
{
if(pTree == NULL)return;
printf("val == %d\tcol == %d\n",pTree->nValue,pTree->nColor);
Traversal(pTree->pLeft);
Traversal(pTree->pRight);
}
RBT *FindNode(RBT *pTree,int nNum)
{
if(pTree == NULL)return NULL;
while(pTree)
{
if(pTree->nValue == nNum)
{
return pTree;
}
else if(pTree->nValue > nNum)
{
pTree = pTree->pLeft;
}
else
{
pTree = pTree->pRight;
}
}
return NULL;
}
void DelNode(RBT *pTree,int nNum)
{
//查找
RBT *pTemp = NULL;
pTemp = FindNode(pTree,nNum);
if(pTemp == NULL)return;
//分析孩子情况
RBT *pMark = NULL;
if(pTemp->pLeft != NULL && pTemp->pRight != NULL)
{
pMark = pTemp;
pTemp = pTemp->pLeft;
while(pTemp->pRight != NULL)
{
pTemp = pTemp->pRight;
}
//值覆盖
pMark->nValue = pTemp->nValue;
}
//颜色
RBT *pNode = pTemp->pFather;
//1.根 且无孩子
if(pNode == NULL && pTemp->pLeft == NULL && pTemp->pRight == NULL)
{
pRBT = NULL;
free(pTemp);
pTemp = NULL;
return;
}
//2.根 且有一个红孩子
if(pNode == NULL && (pTemp->pLeft != NULL || pTemp->pRight != NULL))
{
pRBT = pTemp->pLeft ? pTemp->pLeft : pTemp->pRight;
pRBT->nColor = BLACK;
pRBT->pFather = NULL;
free(pTemp);
pTemp = NULL;
return;
}
//3.非根 红色
if(pTemp->nColor == RED)
{
if(pTemp == pNode->pLeft)
{
pNode->pLeft = NULL;
}
else
{
pNode->pRight = NULL;
}
free(pTemp);
pTemp = NULL;
return;
}
//4.非根 黑色 且有一个红孩子
if(pTemp->nColor == BLACK && (pTemp->pLeft != NULL || pTemp->pRight != NULL))
{
if(pTemp == pNode->pLeft)
{
pNode->pLeft = pTemp->pLeft ? pTemp->pLeft:pTemp->pRight;
pNode->pLeft->pFather = pNode;
pNode->pLeft->nColor = BLACK;
}
else
{
pNode->pRight = pTemp->pLeft ? pTemp->pLeft:pTemp->pRight;
pNode->pRight->pFather = pNode;
pNode->pRight->nColor = BLACK;
}
free(pTemp);
pTemp = NULL;
return;
}
//5.非根 黑 且无孩子
RBT *pBrother = GetUncle(pTemp);
//假删除
if(pTemp == pNode->pLeft)
{
pNode->pLeft = NULL;
}
else
{
pNode->pRight = NULL;
}
pMark = pTemp;
while(1)
{
//5.1兄弟是红的
if(pBrother->nColor == RED)
{
pBrother->nColor = BLACK;
pNode->nColor = RED;
//5.1.1兄弟是父亲的左
if(pBrother == pNode->pLeft)
{
RightRotate(&pNode);
pBrother = pNode->pLeft;
continue;
}
//5.1.2兄弟是父亲的右
if(pBrother == pNode->pRight)
{
LeftRotate(&pNode);
pBrother = pNode->pRight;
continue;
}
}
//5.2兄弟是黑的
if(pBrother->nColor == BLACK)
{
//5.2.1两个侄子全黑
if((pBrother->pLeft == NULL && pBrother->pRight == NULL)||
((pBrother->pLeft != NULL && pBrother->pLeft->nColor == BLACK)&&
(pBrother->pRight != NULL && pBrother->pRight->nColor == BLACK)))
{
//5.2.1.1父亲是红的
if(pNode->nColor == RED)
{
pNode->nColor = BLACK;
pBrother->nColor = RED;
break;
}
//5.2.1.2父亲是黑色的
if(pNode->nColor == BLACK)
{
pBrother->nColor = RED;
pTemp = pNode;
pNode = pTemp->pFather;
//根
if(pNode == NULL)
{
break;
}
pBrother = GetUncle(pTemp);
continue;
}
}
//5.2.2左侄子红,右侄子黑
if((pBrother->pLeft != NULL && pBrother->pLeft->nColor == RED)&&
(pBrother->pRight == NULL || pBrother->pRight->nColor == BLACK))
{
//5.2.2.1兄弟是父亲的右
if(pBrother == pNode->pRight)
{
pBrother->nColor = RED;
pBrother->pLeft->nColor = BLACK;
RightRotate(&pBrother);
pBrother = pNode->pRight;
continue;
}
//5.2.2.2兄弟是父亲的左
if(pBrother == pNode->pLeft)
{
pBrother->nColor = pNode->nColor;
pNode->nColor = BLACK;
pBrother->pLeft->nColor = BLACK;
RightRotate(&pNode);
break;
}
}
//5.2.3右侄子是红
if(pBrother->pRight != NULL && pBrother->pRight->nColor == RED)
{
//5.2.3.1兄弟是父亲的左
if(pBrother == pNode->pLeft)
{
pBrother->nColor = RED;
pBrother->pRight->nColor = BLACK;
LeftRotate(&pBrother);
pBrother = pNode->pLeft;
continue;
}
//5.2.3.2兄弟是父亲的右
if(pBrother == pNode->pRight)
{
pBrother->nColor = pNode->nColor;
pNode->nColor = BLACK;
pBrother->pRight->nColor = BLACK;
LeftRotate(&pNode);
break;
}
}
}
}
free(pMark);
pMark = NULL;
}
int main()
{
int arr[] = {11,2,14,1,7,15,5,8};
CreateRBT(arr,sizeof(arr)/sizeof(arr[0]));
Traversal(pRBT);
printf("---------------------------\n");
//AddNode(pRBT,4);
//Traversal(pRBT);
DelNode(pRBT,1);
Traversal(pRBT);
printf("---------------------------\n");
DelNode(pRBT,11);
Traversal(pRBT);
printf("---------------------------\n");
DelNode(pRBT,15);
Traversal(pRBT);
printf("---------------------------\n");
DelNode(pRBT,2);
Traversal(pRBT);
printf("---------------------------\n");
return 0;
}