红黑树的插入的实现

本文算法实现思想来自算法导论。感觉容易忘记,所以记下来当做学习笔记。

红黑树的性质:

性质1. 节点是红色或黑色。

性质2. 根是黑色。

性质3. 所有叶子都是黑色(叶子是NIL节点)。

性质4. 每个红色节点必须有两个黑色的子节点。(从每个叶子到根的所有路径上不能有两个连续的红色节点。)

性质5. 从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点。


红黑树的插入操作可分步进行,首先进行二叉搜索树的插入操作,然后再对颜色进行调整。

首选,令x指向被插入元素,设置x的颜色为红色。下面分情况讨论:

  1. 如果x的父亲是黑色,那么不需进行调整。
  2. 如果x的父亲是红色,那么需要分情况进行讨论。

2.1.如果x的父亲在左子树上

2.1.1.如果x的父亲的兄弟同样为红色。


x的父亲P的兄弟U同样为红色,那么调整颜色,令G为红色,P和U为黑色,让x指向G,继续调整下去。

2.1.2.如果x的父亲的兄弟为黑色

2.1.2.1.x在右子树上

让P左旋,转化成情况2.1.2.2,继续调整。

2.1.2.2.x在左子树上

调整颜色,把G变为红色,P变为黑色,然后对G左旋。

2.2.如果x的父亲在右子树上,与上面情况相似,不详细讨论。

2.1.1.如果x的父亲的兄弟同样为红色。

2.1.2.如果x的父亲的兄弟为黑色

    2.1.2.1.x在左子树上

    2.1.2.2 .x在右子树上

头文件:

//rb.h
#include<iostream>
using namespace std;

typedef int type;
typedef struct RedBlackTreeNode{
    type key;
	type color;// red 0,black 1
	struct RedBlackTreeNode * left;
	struct RedBlackTreeNode * right;
	struct RedBlackTreeNode * parent;

}node;
详细算法:

#include"rb.h"

/*
*中序遍历输出
*/
int printTree(node *pa){
	if(pa==NULL){
	    return 0;
	}
    node *p=pa;  
	printTree(p->left);
	cout<<p->key<<"+"<<p->color<<"  ";
	printTree(p->right);
	return 0;
}
/*
*建立一个红黑树,返回根的指针
*/
node * initRBTree(){
    node * root=NULL;
	return root;
	
}
/*
*非递归的方法来实现向BST树的插入操作
*/
node * BSTInsert(node ** root,type key){
    node * p=*root;
	node * tem=NULL;
    node * tNode=(node *)malloc(sizeof(node));
    tNode->key=key;
    tNode->color=1;
    tNode->left=tNode->right=tNode->parent=NULL;
	if(!(*root))
	{
	    (*root)=tNode;
	     return *root;
	}
	while(p)
	{
		if(p->key>=key)
		{
			if(p->left)
			{
			  p=p->left;  
			}else
			{
			  p->left=tNode;
              p->left->parent=p;
			  return tNode;
			}
		}else
		{
			if(p->right)
			{
				p=p->right;
			}else 
			{
			   p->right=tNode;
			   p->right->parent=p;
			   return tNode;
			}		
		}
	}
}

/*
*红黑树的插入操作
*实现方法参见 麻省理工学院 算法导论公开课 第十节(可以在网易公开课上查看)
*/
int RBTInsert(node ** root,type key)
{
    node * knode=BSTInsert(root,key);
	knode->color=0;//初始颜色设置为红色
	while((knode!=(*root))&&(knode->parent->color==0)&&(knode->color==0))
	{   /*下面是category A*/
		if(knode->parent->parent->left==knode->parent)
		{
			if(knode->parent->parent->right&&knode->parent->parent->right->color==0)
			{
				knode->parent->parent->right->color=1;
				knode->parent->color=1;
				knode->parent->parent->color=0;
                knode=knode->parent->parent;<strong>//2.1.1</strong>
			}else if(knode==knode->parent->right)
			{
				node * A=knode->parent;
                node * B=knode;
				node * C=knode->parent->parent;
				B->parent=C;
				C->left=B;
				A->right=B->left;
                B->left=A;
				A->parent=B;//2.1.2.1

				if(C->parent)
				{
				   if(C->parent->right==C)
				   {
			    		C->parent->right=B;
				   }else if(C->parent->left==C)
				   {
		     			C->parent->left=B;
				   }
				   B->parent=C->parent;
				   C->left=B->right;
				   B->right=C;
				   C->parent=B;
				   B->color=1;
				   C->color=0;
				}//2.1.2.2
			}else if(knode==knode->parent->left )
			{
			    node * B=knode->parent;
                node * A=knode;
				node * C=knode->parent->parent;
				if(C->parent)
				{
				   if(C->parent->right==C)
				   {
			    		C->parent->right=B;
				   }else if(C->parent->left==C)
				   {
		     			C->parent->left=B;
				   }
				   B->parent=C->parent;
				   C->left=B->right;
				   B->right=C;
				   C->parent=B;
				   B->color=1;
				   C->color=0;
				}//2.1.2.2
			}
			/*category A结束*/
			/*下面是: category B,大致与A相同,只是在右子树上*/
		}else
		{
			if(knode->parent->parent->left&&knode->parent->parent->left->color==0)
			{
				knode->parent->color=1;
				knode->parent->parent->color=0;
				knode->parent->parent->left->color=1;
				knode=knode->parent->parent;//case 1
			}else if(knode->parent->left==knode)
			{
			    node *A=knode;
				node *B=knode->parent;
				node *C=knode->parent->parent;

				C->right=A;
				A->parent=C;
				B->parent=A;
				B->left=A->right;
				A->right=B;//case 2

				if(C->parent)
				{
					if(C->parent->left==C)
					{
						C->parent->left=A;
					}else
					{
						C->parent->right=A;
					}
					A->parent=C->parent;
					C->right=A->left;
					A->left=C;
					C->parent=A;					
					C->color=0;
					A->color=1;//case 3
				}
			}else if(knode->parent->right==knode)
			{
			    node *B=knode;
				node *A=knode->parent;
				node *C=knode->parent->parent;
				if(C->parent)
				{
					if(C->parent->left==C)
					{
						C->parent->left=A;
					}else
					{
						C->parent->right=A;
					}
					A->parent=C->parent;
					C->right=A->left;
					A->left=C;
					C->parent=A;					
					C->color=0;
					A->color=1;//case 3
				} 
			}
		    
		}
	(*root)->color=1;
	}//while
   (*root)->color=1;
	return 0;


}
/*
*测试用主函数
*/
int main(){
    node * root=initRBTree();
	int a[13]={8,7,9,12,14,5,4,6,10,11,19,3,1};
	for(int i=0;i<13;i++){
	   RBTInsert(&root,a[i]);
	   	printTree(root);
	    cout<<endl;
	}
	getchar();
	return 0;

}


图片来自维基百科

参考资料:

  1. 算法导论



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值