红黑树(二) insert

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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值