BST特点:
1.每个节点的颜色非黑即红
2.根节点是黑色
3.树中终端节点(NIL)也称哨兵均为黑色
4.没有两个红节点互为父子关系
5.从任意节点出发到其所能到达的所有终端节点的各条路径上的黑节点的数目完全相同
添加结点情况分类:
1.若树为空,则添加的结点X为树的根,并且X的颜色为黑色
2.若父亲节点为黑节点,则将X插入
3.若父亲节点是红色
3.1 若叔叔节点是红的,则将父亲变黑,将叔叔变黑,将爷爷变红,并且将爷爷变为新的X,然后向上调整
注:这是还要检测爷爷节点是否为根,若为根,则将其变黑,结束
3.2: 若叔叔为黑
3.2.1若父亲是爷爷的左,X为父亲的右孩子,将X的父亲变为新的X,以X为支点左旋后,X为父亲的右孩子,将X的父亲变为黑色,爷爷变红,以爷爷为支点右旋,结束
3.2.2 父亲为爷爷的右,X为父亲的左孩子,将X的父亲变为新的X,以X为支点右旋后,X为父亲的右孩子,将X的父亲变为黑色,爷爷变红,以爷爷为支点左旋,结束
代码
RBT节点删除情况分析:
1.删除的是根节点,并且没有孩子,可直接删除
2.删除的是根节点,并且只有一个孩子,直接删除,并把孩子变为黑色
3.Z(为真正被删除的节点)若为红色,便可以直接删除
4.Z是黑色的,且有一个红孩子,将爷爷和孩子连在一起,并将Z删除,将孩子变黑。
5.Z是黑色,并且非根节点,无孩子
5.1.Z的兄弟为红色
5.1.1兄弟为父亲的右,将兄弟变黑,父亲变红,以父亲为支点进行左旋
5.1.2兄弟为父亲的左,将兄弟变黑,父亲变红,以父亲为支点进行右旋
5.2.Z的兄弟为黑色
5.2.1.两个侄子全黑
5.2.1.1.Z的父亲为红色,把兄弟变红,父亲变黑,结束
5.2.1.2.Z的父亲为黑色,把兄弟变红,父亲变为新的Z,向上层调整
5.2.2.两个侄子左红右黑
5.2.2.1.兄弟是父亲的右,把兄弟变红,左侄子变黑,以兄弟为支点右旋,更新兄弟。
5.2.2.2.兄弟是父亲的左,将左侄子变黑,父亲的颜色变为兄弟的颜色,把父亲变黑,以父亲为支点右旋,结束
5.2.3.左侄子为黑,右侄子为红
5.2.3.1.兄弟为父亲的右,将右侄子变黑,兄弟的颜色变味父亲的颜色,把父亲变黑,再以父亲为支点左旋,结束
5.2.3.2.兄弟为父亲的左,将兄弟变红,把右侄子变黑,以兄弟为支点进行左旋,更新兄弟
、
#include<stdio.h> #include<stdlib.h> typedef struct node { int nValue; int nColor; struct node *pLeft; struct node *pRight; struct node *pFather; }RBT; enum COLOR{RED,BLACK}; RBT *pRBT = NULL; void RightRotate(RBT **pTree) { if(*pTree == NULL)return; RBT *pNode = NULL; RBT *pMark = NULL; pNode = *pTree; 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)return; RBT *pNode = NULL; RBT *pMark = NULL; pNode = *pTree; 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 *FindNode(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("error.\n"); return NULL; } } } RBT *GetUncle(RBT *pNode) { if(pNode == pNode->pFather->pLeft) { return pNode->pFather->pRight; } else { return pNode->pFather->pLeft; } } void InsertNode(int nNum) { RBT *pTemp = NULL; pTemp = (RBT*)malloc(sizeof(RBT)); pTemp->nValue = nNum; pTemp->nColor = RED; pTemp->pLeft = NULL; pTemp->pRight = NULL; pTemp->pFather = NULL; RBT *pNode = NULL; //1.空树 if(pRBT == NULL) { pRBT = pTemp; pRBT->nColor = BLACK; return; } //查找被添加位置 pNode = FindNode(pRBT,nNum); if(pNode == NULL)return; //与父亲关联 if(pNode->nValue > nNum) { pNode->pLeft = pTemp; } else { pNode->pRight = pTemp; } pTemp->pFather = pNode; //2.父亲黑色 直接放入 结束 if(pNode->nColor == BLACK) { return; } RBT *pUncle = NULL; RBT *pGrandFather = NULL; //3.父亲是红色 while(pNode->nColor == RED) { pUncle = GetUncle(pNode); pGrandFather = pNode->pFather; //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; return; } 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; continue; } //3.2.1.2当前节点是父亲的左 if(pTemp == pNode->pLeft) { //父亲变黑 爷爷变红 以爷爷为支点右旋 pNode->nColor = BLACK; pGrandFather->nColor = RED; RightRotate(&pGrandFather); return; } } //3.2.2父亲是爷爷的右 if(pNode == pGrandFather->pRight) { //3.2.2.1当前节点是父亲的左 if(pTemp == pNode->pLeft) { pTemp = pNode; RightRotate(&pTemp); pNode = pTemp->pFather; continue; } //3.2.2.2当前节点是父亲的右 if(pTemp == pNode->pRight) { pNode->nColor = BLACK; pGrandFather->nColor = RED; LeftRotate(&pGrandFather); return; } } } } } void CreateRBT(int arr[],int nLength) { if(arr == NULL || nLength <= 0)return; int i; for(i = 0;i<nLength;i++) { InsertNode(arr[i]); } } void Traversal(RBT *pTree) { if(pTree == NULL)return; Traversal(pTree->pLeft); printf("color == %d,value == %d\n",pTree->nColor,pTree->nValue); Traversal(pTree->pRight); } RBT *Search(RBT *pTree,int nNum) { if(pTree == NULL)return NULL; while(pTree) { if(pTree->nValue == nNum) { return pTree; } else if(pTree->nValue < nNum) { pTree = pTree->pRight; } else { pTree = pTree->pLeft; } } return NULL; } RBT *GetBrother(RBT *pNode) { if(pNode == pNode->pFather->pLeft) { return pNode->pFather->pRight; } else { return pNode->pFather->pLeft; } } void DelNode(int nNum) { //查找 RBT *pNode = NULL; pNode = Search(pRBT,nNum); //检测情况 if(pNode == NULL)return; //两个孩子情况 RBT *pMark = NULL; if(pNode->pLeft != NULL && pNode->pRight != NULL) { pMark = pNode; pNode = pNode->pLeft; while(pNode->pRight) { pNode = pNode->pRight; } pMark->nValue = pNode->nValue; } //1.是根 if(pNode->pFather == NULL ) { //没孩子 if(pNode->pLeft == NULL && pNode->pRight == NULL) { free(pNode); pNode = NULL; pRBT = NULL; return; } //有一个红孩子 if(pNode->pLeft != NULL || pNode->pRight != NULL) { if(pNode->pLeft != NULL) { pRBT = pNode->pLeft; pRBT->nColor = BLACK; pRBT->pFather = NULL; free(pNode); pNode = NULL; return; } if(pNode->pRight != NULL) { pRBT = pNode->pRight; pRBT->nColor = BLACK; pRBT->pFather = NULL; free(pNode); pNode = NULL; return; } } } //2.是红色的 if(pNode->nColor == RED) { if(pNode == pNode->pFather->pLeft) { pNode->pFather->pLeft = NULL; } else { pNode->pFather->pRight = NULL; } free(pNode); pNode = NULL; return; } //3.有一个红孩子 if(pNode->pLeft != NULL || pNode->pRight != NULL) { if(pNode->pLeft != NULL) { if(pNode == pNode->pFather->pLeft) { pNode->pFather->pLeft = pNode->pLeft; } else { pNode->pFather->pRight = pNode->pLeft; } pNode->pLeft->nColor = BLACK; pNode->pLeft->pFather = pNode->pFather; free(pNode); pNode = NULL; return ; } if(pNode->pRight != NULL) { if(pNode == pNode->pFather->pLeft) { pNode->pFather->pLeft = pNode->pRight; } else { pNode->pFather->pRight = pNode->pRight; } pNode->pRight->pFather = pNode->pFather; pNode->pRight->nColor = BLACK; free(pNode); pNode = NULL; return; } } pMark = pNode; //标记原始被删除位置 RBT *pFather = NULL; RBT *pBrother = NULL; pFather = pNode->pFather; pBrother = GetBrother(pNode); if(pNode == pNode->pFather->pLeft) { pNode->pFather->pLeft = NULL; } else { pNode->pFather->pRight = NULL; } //黑 非根且无孩子 while(1) { //兄弟是红色的 if(pBrother != NULL && pBrother->nColor == RED) { //兄弟变黑 父亲变红 以父亲为支点旋转 pBrother->nColor = BLACK; pFather->nColor = RED; if(pBrother == pFather->pLeft) { RightRotate(&pFather); //更新兄弟 pBrother = pFather->pLeft?pFather->pLeft:pFather->pRight; continue; } if(pBrother == pFather->pRight) { LeftRotate(&pFather); pBrother = pFather->pLeft?pFather->pLeft:pFather->pRight; continue; } } //兄弟是黑色的 if(pBrother->nColor == BLACK) { //两个侄子全黑 if((pBrother->pLeft == NULL && pBrother->pRight == NULL ) || (pBrother->pLeft != NULL && pBrother->pLeft->nColor == BLACK &&pBrother->pRight != NULL && pBrother->pRight->nColor == BLACK)) { //父亲是红 if(pFather->nColor == RED) { //兄弟变红 父亲变黑 结束 pBrother->nColor = RED; pFather->nColor = BLACK; break; } //父亲是黑的 if(pFather->nColor == BLACK) { //兄弟变红 以父亲为新的当前节点向上调整 pBrother->nColor = RED; pNode = pFather; pFather = pNode->pFather; if(pFather == NULL) { break; } //更新兄弟 pBrother = GetBrother(pNode); continue; } } //左侄子红 右侄子黑 if(pBrother->pLeft != NULL && pBrother->pLeft->nColor == RED && (pBrother->pRight == NULL || pBrother->pRight->nColor == BLACK)) { //兄弟是父亲的右 if(pBrother == pFather->pRight) { //兄弟边红 左侄子变黑 pBrother->nColor = RED; pBrother->pLeft->nColor = BLACK; //以兄弟为支点右旋 RightRotate(&pBrother); //更新兄弟 pBrother = pBrother->pFather; continue; } //兄弟是父亲的左 if(pBrother == pFather->pLeft) { //左侄子变黑 父亲的颜色给兄弟 父亲 变黑 以父亲为支点右旋 pBrother->pLeft->nColor = BLACK; pBrother->nColor = pFather->nColor; pFather->nColor = BLACK; RightRotate(&pFather); break; } } //右侄子是红的 if(pBrother->pRight != NULL && pBrother->pRight->nColor == RED) { //兄弟是父亲的左 if(pBrother == pFather->pLeft) { //兄弟变红 右侄子变黑 pBrother->nColor = RED; pBrother->pRight->nColor = BLACK; //以兄弟为支点 左旋 LeftRotate(&pBrother); //更新兄弟 pBrother = pBrother->pFather; continue; } //兄弟是父亲的右 if(pBrother == pFather->pRight) { //右侄子变黑 父亲颜色给兄弟 父亲变黑 以父为支点左旋 pBrother->pRight->nColor = BLACK; pBrother->nColor = pFather->nColor; pFather->nColor = BLACK; LeftRotate(&pFather); break; } } } } //释放节点 free(pMark); pMark = NULL; } int main() { int arr[] = {11,2,14,1,7,15,5,8}; CreateRBT(arr,8); Traversal(pRBT); printf("-------------------\n"); //InsertNode(4); DelNode(14); Traversal(pRBT); printf("\n"); //DelNode(11); //Traversal(pRBT); return 0; }