什么是红黑树
红黑树是一种被广泛应用的平衡二叉搜索树。
为了解决BST的不平衡的问题。
它不仅是一个二叉搜索树,还具有以下几个特点:
1.每个节点非红即黑。
2.红黑树的根节点必须是黑色的。
3.叶子下的空节点是哨兵节点,其颜色是黑色。
4.红黑树不允许两个红节点为父子关系。
5.红黑树从任意节点向下出发,其所有能达到各个终端节点的路径上,黑节点的数目必须相同。
以上的几点,确定的红黑树添加规则。
并且,红黑树不会右任意一条路径的长度为其他路径长度的2倍。
添加的情况分析:
设新添加的节点为Z。
1.空树
新来的节点为根,并且将颜色变为黑色。
2.父亲是黑色的
直接将Z放入。
3.父亲为红色的(这种情况下,爷爷 一定是黑色的)
在这种情况下,我们需要的到叔叔的颜色。
3.1叔叔是红色的
将叔叔和父亲的节点颜色变为黑色,爷爷的颜色改为红色,爷爷为新的Z,继续向上讨论。
3.2叔叔为黑色
因为叔叔和父亲的颜色不平等,只能旋转调
3.2.1父亲是爷爷的左
3.2.1.1 Z是父亲的右
即<
父亲是新的Z,以Z为支点左旋。
3.2.1.2 Z是父亲的右
将父亲变为黑色,爷爷变为红色,
以爷爷为支点,右旋。
3.2.2 父亲是爷爷的右
3.2.2.1 Z是父亲的左
即>
父亲是新的Z,以Z为支点右旋。
3.2.2.2 Z是父亲的右
父亲变为黑色,爷爷变为红色,以爷爷为支点左旋。
代码如下:
#include<stdio.h>
#include<stdlib.h>
enum COLOR {RED,BLACK};
typedef struct rbt
{
int nValue;
int nColor;
rbt*pLeft;
rbt*pRight;
rbt*pFather;
}RBT;
RBT*pRBT = NULL;
void RightRotate(RBT*pTree)
{
if(*pTree == NULL || pTree->pLeft == NULL)
return ;
RBT*pNode = *pTree;
RBT*pMark = pTree->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 || nNum <= 0)
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->pRight;
pTree = pTree->pRight;
}
else
{
printf("data error.");
}
}
}
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->nColor = RED;
pTemp->nValue = nNum;
pTemp->pLeft = NULL;
pTemp->pRight = NULL;
pTemp-.pFather = pNode;
//情况分析
//1.空树
if(pNode == NULL)
{
pNode = pTemp;
pNode->nColor = BLACK;
return;
}
//非空树
//连接
if(pNode->nValue > nNum)
{
pNode->pLeft = pTemp;
}
else
{
pNode->pRight = pTemp;
}
//2.父亲是黑色的
if(pNode->nColor == BLACK)
{
return;
}
//3.父亲是红的
RBT*pUncle = NULL;
RBT*pGrandpa = NULL;
while(pNode->nColor == RED)
{
pGrandpa = pNode->pFather;
pUncle = GetUncle(pNode);
//3.1叔叔是红色的
if(pUncle->nColor == RED && pUncle != NULL)
{
pNode->nColor = BLACK;
pUncle->nColor = BLACK;
pGrandpa->nColor = RED;
pTemp = pGrandpa;
pNode = pGrandpa->pFather;
if(pNode == NULL)
{
pRBT->nColor = BLACK;
break;
}
continue;
}
//3.2叔叔是黑色的
if(pUncle->nColor == BLACK || pUncle == NULL)
{
//3.2.1父亲是爷爷的左
if(pNode == pGrandpa->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;
pGrandpa->nColor = RED;
RightRotate(&pGrandpa);
break;
}
}
//3.2.2 父亲是爷爷的右
if(pNode == pGrandpa->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;
pGrandpa->nColor = RED;
LeftRotate(&pGrangpa);
break;
}
}
}
}
}