insert,
1 新增节点的颜色为红色, 这样我们就不用担心黑高度的问题
2 唯一要担心的是,父子节点都为红色,我们要做的是怎么解决这种情况。
#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);
}
void test_rb_insert()
{
RBNode* pTree = pNil;
int arr[] = { 5,3,2,1,4,9,7,13 };
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);
}
}
int main()
{
test_rb_insert();
return 0;
}