#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef enum enColor
{
RED = 0,
BLACK
}Color;
typedef struct stRBNode
{
struct stRBNode* pP;
struct stRBNode* pL;
struct stRBNode* pR;
int key;
Color color;
}RBNode;
RBNode g_nil = { NULL,NULL,NULL,0,BLACK };
RBNode* pNil = &g_nil;
void rb_inorder_print(RBNode* pNode)
{
if (pNode != pNil)
{
rb_inorder_print(pNode->pL);
printf("%d:%d\t",pNode->key,pNode->color);
rb_inorder_print(pNode->pR);
}
}
void rb_preorder_print(RBNode* pNode)
{
if (pNode != pNil)
{
printf("%d:%d\t", pNode->key, pNode->color);
rb_preorder_print(pNode->pL);
rb_preorder_print(pNode->pR);
}
}
void rb_print_tree(RBNode* pNode)
{
printf("####inorder print####\n");
rb_inorder_print(pNode);
printf("\n");
printf("preorder print\n");
rb_preorder_print(pNode);
printf("\n");
}
void rb_l_rotate(RBNode **ppTree,RBNode* pOperNode)
{
RBNode* pRightSon = pOperNode->pR;
if (pRightSon == pNil)
{
printf("opernode %d:%d has no rightson, no need left rotatee\n",pOperNode->key,pOperNode->color);
return;
}
pOperNode->pR = pRightSon->pL;
if (pRightSon->pL != pNil) pRightSon->pL->pP = pOperNode;
pRightSon->pP = pOperNode->pP;
if (pOperNode->pP == pNil)
{
*ppTree = pRightSon;
}
else if (pOperNode->pP->pL == pOperNode)
{
pOperNode->pP->pL = pRightSon;
}
else
{
pOperNode->pP->pR = pRightSon;
}
pRightSon->pL = pOperNode;
pOperNode->pP = pRightSon;
}
void rb_r_rotate(RBNode** ppTree, RBNode* pOperNode)
{
RBNode* pLeftSon = pOperNode->pL;
if (pLeftSon == pNil)
{
printf("opernode %d:%d has no leftson, no need right rotatee\n", pOperNode->key, pOperNode->color);
return;
}
pOperNode->pL = pLeftSon->pR;
if (pLeftSon->pR != pNil) pLeftSon->pR->pP = pOperNode;
pLeftSon->pP = pOperNode->pP;
if (pOperNode->pP == pNil)
{
*ppTree = pLeftSon;
}
else if (pOperNode->pP->pL == pOperNode)
{
pOperNode->pP->pL = pLeftSon;
}
else
{
pOperNode->pP->pR = pLeftSon;
}
pLeftSon->pR = pOperNode;
pOperNode->pP = pLeftSon;
}
RBNode* rb_new_node(int key)
{
RBNode* pNewNode = (RBNode*)malloc(sizeof(RBNode));
if (pNewNode == NULL)
{
printf("malloc for %d fail \n",key);
return pNil;
}
pNewNode->key = key;
pNewNode->pP = pNil;
pNewNode->pL = pNil;
pNewNode->pR = pNil;
pNewNode->color = RED;
return pNewNode;
}
void rb_fixup_if_parent_is_grandpa_leftson(RBNode **ppTree,RBNode **ppOperNode,RBNode **ppParentNode)
{
RBNode* pOperNode = *ppOperNode;
RBNode* pParentNode = *ppParentNode;
RBNode* pGrandpaNode = pParentNode->pP;
RBNode* pUncleNode;
printf("%s opernode %d:%d parentnode %d:%d \n", __func__, pOperNode->key, pOperNode->color,
pParentNode->key, pParentNode->color);
pUncleNode = pGrandpaNode->pR;
if (pUncleNode != pNil && pUncleNode->color == RED)
{
printf("uncle %d:%d is also red\n", pUncleNode->key, pUncleNode->color);
pParentNode->color = BLACK;
pUncleNode->color = BLACK;
pGrandpaNode->color = RED;
*ppOperNode = pGrandpaNode;
*ppParentNode = pGrandpaNode->pP;
}
else if (pParentNode->pR == pOperNode)
{
printf("opernode is right son of parentnode, need left rotate parentnode \n");
rb_l_rotate(ppTree,pParentNode);
*ppOperNode = pParentNode;
*ppParentNode = pOperNode;
}
else
{
printf("right rotate grandpanode %d:%d\n", pGrandpaNode->key, pGrandpaNode->color);
pParentNode->color = BLACK;
pGrandpaNode->color = RED;
rb_r_rotate(ppTree,pGrandpaNode);
}
}
void rb_fixup_if_parent_is_grandpa_rightson(RBNode** ppTree, RBNode** ppOperNode, RBNode** ppParentNode)
{
RBNode* pOperNode = *ppOperNode;
RBNode* pParentNode = *ppParentNode;
RBNode* pGrandpaNode = pParentNode->pP;
RBNode* pUncleNode;
printf("%s opernode %d:%d parentnode %d:%d \n",__func__,pOperNode->key,pOperNode->color,
pParentNode->key,pParentNode->color);
pUncleNode = pGrandpaNode->pL;
if (pUncleNode != pNil && pUncleNode->color == RED)
{
printf("uncle %d:%d is also red\n",pUncleNode->key,pUncleNode->color);
pParentNode->color = BLACK;
pUncleNode->color = BLACK;
pGrandpaNode->color = RED;
*ppOperNode = pGrandpaNode;
*ppParentNode = pGrandpaNode->pP;
}
else if (pParentNode->pL == pOperNode)
{
printf("opernode is left son of parentnode, need right rotate parentnode \n");
rb_r_rotate(ppTree, pParentNode);
*ppOperNode = pParentNode;
*ppParentNode = pOperNode;
}
else
{
printf("left rotate grandpanode %d:%d\n",pGrandpaNode->key,pGrandpaNode->color);
pParentNode->color = BLACK;
pGrandpaNode->color = RED;
rb_l_rotate(ppTree, pGrandpaNode);
}
}
void rb_fixup(RBNode** ppTree, RBNode* pOperNode)
{
RBNode* pParentNode = pOperNode->pP;
RBNode* pGrandpaNode;
while (pParentNode != pNil && pParentNode->color == RED &&
pOperNode != pNil && pOperNode->color == RED)
{
pGrandpaNode = pParentNode->pP;
if (pGrandpaNode == pNil)
{
printf("grandpa node is nil, opernode %d:%d parentnode %d:%d \n",
pOperNode->key,pOperNode->color,pGrandpaNode->key,pGrandpaNode->color);
break;
}
if (pGrandpaNode->pL == pParentNode)
{
rb_fixup_if_parent_is_grandpa_leftson(ppTree, &pOperNode, &pParentNode);
}
else
{
rb_fixup_if_parent_is_grandpa_rightson(ppTree, &pOperNode, &pParentNode);
}
}
(*ppTree)->color = BLACK;
}
void rb_insert(RBNode** ppTree, int key)
{
RBNode* pNewNode = rb_new_node(key);
if (pNewNode == pNil) return;
RBNode* pParentNode = pNil;
RBNode* pLoopNode = *ppTree;
while (pLoopNode != pNil)
{
pParentNode = pLoopNode;
if (pLoopNode->key >= key)
{
pLoopNode = pLoopNode->pL;
}
else
{
pLoopNode = pLoopNode->pR;
}
}
pNewNode->pP = pParentNode;
if (pParentNode == pNil)
{
*ppTree = pNewNode;
}
else if (pParentNode->key >= key)
{
pParentNode->pL = pNewNode;
}
else
{
pParentNode->pR = pNewNode;
}
rb_fixup(ppTree, pNewNode);
}
RBNode* rb_min(RBNode* pNode)
{
RBNode* pMin = pNil;
while (pNode != pNil)
{
pMin = pNode;
pNode = pNode->pL;
}
return pMin;
}
RBNode* rb_next(RBNode* pNode)
{
if (pNode->pR != pNil)
{
return rb_min(pNode->pR);
}
while (pNode->pP != pNil && pNode->pP->pR == pNode)
{
pNode = pNode->pP;
}
return pNode->pP;
}
void rb_del_fixup_if_is_leftson(RBNode** ppTree, RBNode** ppReplaceNode)
{
RBNode* pTree = *ppTree;
RBNode* pParent, *pNeighbor, *pReplaceNode;
pReplaceNode = *ppReplaceNode;
pParent = pReplaceNode->pP;
pNeighbor = pReplaceNode->pP->pR;
if (pNeighbor->color == RED)
{
pParent->color = RED;
pNeighbor->color = BLACK;
rb_l_rotate(ppTree, pParent);
return;
}
RBNode* pNeighborLSon, * pNeighborRSon;
pNeighborLSon = pNeighbor->pL;
pNeighborRSon = pNeighbor->pR;
if (pNeighborLSon->color == BLACK && pNeighborRSon->color == BLACK)
{
pNeighbor->color = RED;
*ppReplaceNode = pParent;
return;
}
else if (pNeighborLSon->color == RED)
{
pNeighborLSon->color = BLACK;
pNeighbor->color = RED;
rb_r_rotate(ppTree, pNeighbor);
}
else
{
pNeighbor->color = pParent->color;
pNeighborRSon->color = BLACK;
pParent->color = BLACK;
rb_l_rotate(ppTree, pParent);
*ppReplaceNode = *ppTree;
}
}
void rb_del_fixup_if_is_rightson(RBNode** ppTree, RBNode** ppReplaceNode)
{
RBNode* pTree = *ppTree;
RBNode* pParent, * pNeighbor, * pReplaceNode;
pReplaceNode = *ppReplaceNode;
pParent = pReplaceNode->pP;
pNeighbor = pReplaceNode->pP->pL;
if (pNeighbor->color == RED)
{
pParent->color = RED;
pNeighbor->color = BLACK;
rb_r_rotate(ppTree, pParent);
return;
}
RBNode* pNeighborLSon, * pNeighborRSon;
pNeighborLSon = pNeighbor->pL;
pNeighborRSon = pNeighbor->pR;
if (pNeighborLSon->color == BLACK && pNeighborRSon->color == BLACK)
{
pNeighbor->color = RED;
*ppReplaceNode = pParent;
return;
}
else if (pNeighborRSon->color == RED)
{
pNeighborRSon->color = BLACK;
pNeighbor->color = RED;
rb_l_rotate(ppTree, pNeighbor);
}
else
{
pNeighbor->color = pParent->color;
pNeighborLSon->color = BLACK;
pParent->color = BLACK;
rb_r_rotate(ppTree, pParent);
*ppReplaceNode = *ppTree;
}
}
void rb_del_fixup(RBNode** ppTree, RBNode* pReplaceNode)
{
RBNode* pTree = *ppTree;
RBNode* pParent, *pNeighbor;
while (pReplaceNode != pTree && pReplaceNode->color == BLACK)
{
pParent = pReplaceNode->pP;
if (pParent == pNil)
{
printf("Error happened, pParent is nil \n");
break;
}
if (pReplaceNode == pParent->pL)
{
pNeighbor = pParent->pR;
if (pNeighbor == pNil)
{
printf("Error happened, pRightNeighbor is nil \n");
break;
}
rb_del_fixup_if_is_leftson(ppTree,&pReplaceNode);
}
else
{
pNeighbor = pParent->pL;
if (pNeighbor == pNil)
{
printf("Error happened, pLeftNeighbor is nil \n");
break;
}
rb_del_fixup_if_is_rightson(ppTree,&pReplaceNode);
}
}
pReplaceNode->color = BLACK;
}
RBNode *rb_del(RBNode** ppTree, RBNode *pDelNode)
{
RBNode* pRealDelNode, * pReplaceNode;
if (pDelNode->pL == pNil || pDelNode->pR == pNil)
{
pRealDelNode = pDelNode;
}
else
{
pRealDelNode = rb_next(pDelNode);
}
if (pRealDelNode->pL != pNil)
{
pReplaceNode = pRealDelNode->pL;
}
else
{
pReplaceNode = pRealDelNode->pR;
}
pReplaceNode->pP = pRealDelNode->pP;
if (pRealDelNode->pP == pNil)
{
*ppTree = pReplaceNode;
}
else if (pRealDelNode->pP->pL == pRealDelNode)
{
pRealDelNode->pP->pL = pReplaceNode;
}
else
{
pRealDelNode->pP->pR = pReplaceNode;
}
if (pRealDelNode != pDelNode)
{
pDelNode->key = pRealDelNode->key;
}
if (pRealDelNode->color == BLACK)
{
rb_del_fixup(ppTree, pReplaceNode);
}
return pRealDelNode;
}
RBNode* rb_find(RBNode** ppTree, int key)
{
RBNode* pNode = *ppTree;
while (pNode != pNil)
{
if (pNode->key == key)
{
return pNode;
}
else if (key < pNode->key)
{
pNode = pNode->pL;
}
else
{
pNode = pNode->pR;
}
}
return pNil;
}
void test_rb_insert()
{
RBNode* pTree = pNil;
int arr[] = { 5,3,2,1,4};
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
printf("@begin insert: %d \n",arr[i]);
rb_insert(&pTree,arr[i]);
rb_print_tree(pTree);
}
RBNode* pFindNode = rb_find(&pTree, 3);
if (pFindNode != pNil)
{
printf("begin del node 3 \n");
pFindNode = rb_del(&pTree, pFindNode);
free(pFindNode);
rb_print_tree(pTree);
}
}
int main()
{
test_rb_insert();
return 0;
}
删除的逻辑比插入逻辑复杂一些,
需要依靠neibor节点和neibor的儿子来实现黑高度的平衡。