红黑树的实现代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct node
{
	int data;
	struct node *p;
	struct node *left;
	struct node *right;
	char color;
}node,*linktree;

void Create_Tree();
void Insert(linktree T,int i);
void Insert_Fix(linktree s,linktree z);
void Left_Rotate(linktree s,linktree z);
void Right_Rotate(linktree s,linktree z);
void Inorder(linktree s);
void Delete(linktree z);
linktree  Tree_Successor(linktree s);
void Delete_Fix(linktree s);

linktree Nil;
static linktree root;

int main()
{
	Nil=(linktree)malloc(sizeof(node));//定义外节点,统一设置为Nil;
	Nil->color='B';
	Nil->p=NULL;
	Nil->left=NULL;
	Nil->right=NULL;
	Nil->data=0;
	Create_Tree();
	return 0;
}

void Create_Tree()
{
	linktree s;
	
	int a[]={11,2,14,1,7,15,5,4,8};
	int i;
	root=(linktree)malloc(sizeof(node));//定义跟节点,着色为黑色
	root->data=11;
	root->p=Nil;
	root->left=Nil;
	root->right=Nil;
	root->color='B';
	printf("root=%p\n",root);
	for(i=1;i<sizeof(a)/sizeof(int);i++)
	{
		printf("root=%p\n",root);
		
		Insert(root,a[i]);	
		printf("root->data=%d\n",root->data);
	}
	Inorder(root);
	Delete(root);
	printf("\n\n");
	Inorder(root);
}

void Insert(linktree T,int i)
{
	linktree s,y;
	s=T;
	printf("%d ",i);
	while(s!=Nil)//获取插入节点
	{
		y=s;//记下插入节点的父节点
		if(s->data>i)
			s=s->left;
		else
			s=s->right;
	}
	s=(linktree)malloc(sizeof(node));
	if(y->data>i)//插入y的左节点
	{
		y->left=s;
		s->p=y;
		s->data=i;
		s->right=Nil;
		s->left=Nil;
		s->color='R';
	}
	else//插入y的右节点
	{
		y->right=s;
		s->p=y;
		s->data=i;
		s->right=Nil;
		s->left=Nil;
		s->color='R';
	}
	Insert_Fix(T,s);
}

void Left_Rotate( linktree s,linktree z)//为了保持红黑树的特性 对节点z 做左旋操作,节点z 的右孩子必须不是Nul
{
	
	linktree y;
	printf("左旋的值为:%d\n",z->data);
	y=z->right;
	z->right=y->left;
	if(y->left!=Nil)
		y->left->p=z;
	y->p=z->p;
	if(z->p==Nil) //判断z是z的父节点的左子树还是右子树
	{
		root=y; //把y赋值给跟节点
		printf("改变左旋root?==%p,%d\n",root,root->data);
	}
	else{
		if(z->p->left==z)
			z->p->left=y;
		else 
			z->p->right=y;
		}
	y->left=z; //把z放到y的左子树上
	z->p=y;

}

void Right_Rotate(linktree s,linktree z)//为了保持红黑树的特性 对节点z 做右旋操作,节点z 的左孩子必须不是Nul
{
	linktree y;
	y=z->left;
	z->left=y->right;
	if(y->right!=Nil)
		y->right->p=z;
	y->p=z->p;
	if(z->p==Nil)
		{
			root=y; //如果z是根节点,则把y变为跟节点
		}
	else 
		{
			if(z->p->left==z)
				z->p->left=y;
			else
				{
					z->p->right=y;
				}
				
		}
	y->right=z;
	z->p=y;
}	

void Insert_Fix(linktree s,linktree z) //修复插入过程中产生的不符合红黑树特性的情况
{
	linktree y;
	while(z->p->color=='R')
	{
		if(z->p==z->p->p->left) //如果Z的父节点是其祖父节点的左孩子
		{
			y=z->p->p->right; //把z的叔父赋值给y
			if(y->color=='R') //z的叔父为红色,符合第一种情况,直接把z的父亲,z的叔父着色为黑色,
				//把z的祖父着色为红色(为了保证红黑树的的第五条特性成立(每个节点到其子孙路径上的所有节点包含相同的黑节点))
			{
				z->p->color='B';
				y->color='B';
				z->p->p->color='R';
				z=z->p->p; // z上溯..
			}
			else
			{
				if(z->p->right==z)//第二种情况 ,z是其父节点的右孩子,通过一次左旋把他转化成第三种情况
				{
					z=z->p;
					Left_Rotate(s,z);
				}
				//第三种情况,z是其父节点的做孩子
				z->p->color='B';
				z->p->p->color='R';
				Right_Rotate(s,z->p->p);
			}
		
		}
		else //如果Z的父节点是其祖父节点的右孩子
		{
			y=z->p->p->left;
			if(y->color=='R')
			{
				z->p->color='B';
				y->color='B';
				z->p->p->color='R';
				z=z->p->p;
			}
			else
			{
				if(z->p->left==z)//右旋之..
				{
					z=z->p;
					Right_Rotate(s,z);
				}
				z->p->color='B';
				z->p->p->color='R';
				Left_Rotate(s,z->p->p);
			}
		}
	}
	root->color='B';
}

void Inorder(linktree s) //树的遍历
{
	if(s!=Nil)
	{
		Inorder(s->left);
		printf("data=%d,color=%c,left=%d,right=%d,parent=%d\n",s->data,s->color,s->left->data,s->right->data,s->p->data);
		Inorder(s->right);
	}
}

void Delete(linktree z)
{
	linktree x,y;
	if(z->left==Nil || z->right==Nil) //找到需要删除的节点
		y=z;
	else
		y=Tree_Successor(z);
	if(y->left!=Nil)
		x=y->left;
	else
		x=y->right;
	x->p=y->p;
	if(y->p==Nil)
		root=y;
	else if(y->p->left==y)
		y->p->left=x;
	else
		y->p->right=x;
	if (y!=z)
		z->data=y->data;
	if(y->color=='B')
		Delete_Fix(x);

}

linktree  Tree_Successor(linktree s) //查找节点的直接后继
{
	linktree y;
	if(s->right!=Nil)
	{
		y=s->right;
		while(y->left!=Nil)
		{
			y=y->left;
		}
	}
	else
	{
		y=s->p;
		while(y!=Nil && s==y->right)
		{
			s=y;
			y=y->p;
		}
	}
	return y;
}

void Delete_Fix(linktree x) //删除节点后恢复红黑树的特性
{
	linktree w;
	while(x!=root&&x->color=='B')
	{
		if(x==x->p->left)
		{
			w=x->p->right;
			if(w->color=='R')
			{
				w->color='B';
				x->p->color='R';
				Left_Rotate(root,x->p);
			}
			if(w->left->color=='B' && w->right->color=='B')
			{
				w->color='R';
				x=x->p;
			}
			else 
			{
				if(w->right->color=='B')
				{
					w->left->color='B';
					w->color='R';
					Right_Rotate(root,w);
					w=x->p->right;
				}
				w->color=x->p->color;
				x->p->color='B';
				w->right->color='B';
				Left_Rotate(root,x->p);
				x=root;
			}
		}
		else
		{
			w=x->p->left;
			if(w->color=='R')
			{
				w->color='B';
				x->p->color='R';
				Right_Rotate(root,x->p);
			}
			if(w->left->color=='B' && w->right->color=='B')
			{
				w->color='R';
				x=x->p;
			}
			else 
			{
				if(w->left->color=='B')
				{
					w->right->color='B';
					w->color='R';
					Left_Rotate(root,w);
					w=x->p->right;
				}
				w->color=x->p->color;
				x->p->color='B';
				w->left->color='B';
				Right_Rotate(root,x->p);
				x=root;
			}
		}
	}
	x->color='B';
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值