紅黑樹

紅黑樹: 一個平衡的二叉樹,但不是一個完美的平衡二叉樹。 查找在~lgN次比較內結束,但是這樣在動態插入中保持樹的完美平衡代價太高,所以,我們稍微放鬆逛一下限制,希望找到一個能在對數時間內完成查找的數據結構。
五條性質:
性質一:節點是紅色或者是黑色;
在樹裏面的節點不是紅色的就是黑色的,沒有其他顏色,要不怎麼叫紅黑樹呢,是吧。
性質二:根節點是黑色;
根節點總是黑色的。它不能爲紅。
性質三:每個葉節點(NIL或空節點)是黑色;
性質四:每個紅色節點的兩個子節點都是黑色的(也就是說不存在兩個連續的紅色節點);
就是連續的兩個節點不能是連續的紅色,連續的兩個節點的意思就是父節點與子節點不能是連續的紅色。
性質五:從任一節點到其沒個葉節點的所有路徑都包含相同數目的黑色節點;

插入分類:

    1.根

    2.黑色下面

    3紅色下面

        父紅 叔黑================父紅叔紅

        父黑祖父紅  Turn                              父黑叔黑祖父紅(con)

刪除操作: (找真正刪除節點)

    1.兩個孩子

    2.根    一個/零個孩子

    3沒有孩子

================================>

     1.紅色節點

     2.黑色一個紅孩    

    3.黑色沒有孩子 看兄弟

        兄弟紅色  染黑旋轉

        兄弟黑色      

        1)左右雙黑      2)左紅右黑                                                      3)右紅

            兄紅{父紅染黑        右側 兄紅左黑右旋pb(con)                                    右側 兄呈父色   右黑父黑左旋pf

                    父黑 上調}               兄呈父色 左黑父黑右旋pf                        兄紅右黑左旋pb  (con)

            







#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define f(i,l,r) for(int i=l;i<=r;++i)
#define g(i,l,r) for(int i=l;i>=r;--i)

enum Color{black,red};
typedef struct _RBTNode {
	int val;
	int color;
	struct _RBTNode * f,*l,*r;
}rbt;
rbt *pRbt = NULL;
rbt * createNode(int val){
	rbt *p =(rbt *)malloc(sizeof(rbt));
	p->val = val;
	p->f = NULL;
	p->l = NULL;
	p->r = NULL;
	p->color =red;

	return p;
}
void leftTurn(rbt ** pRoot){
	if(pRoot ==NULL) return ;

	rbt * t = *pRoot;
	rbt * pf = t->f;
	rbt * pl = t->l;
	rbt * pr = t->r;
	rbt * prl;
	if(pr)
		prl = t->r->l;
	if(prl)
		prl->f=t;
	t->r=prl;
	pr->l =NULL;
	if(pf==NULL) pRbt =pr;
	else 
	{
		if(pf->l==t)pf->l=pr;
		else
			pf->r=pr;
	}
	pr->f=pf;
	pr->l=t;
	t->f=pr; 
}
void rightTurn(rbt ** pRoot ){
	if(pRoot ==NULL) return ;

	rbt * t = *pRoot;
	rbt * pf = t->f;
	rbt * pl = t->l;
	rbt * pr = t->r;
	rbt * plr;
	if(pl)
		plr = t->l->r;
	if(plr)
		plr->f=t;
	t->l =plr;
	pl->r=NULL;
	if(pf==NULL)
	{
		pRbt=pl;
	}
	else 
	{
		if(pf->l==t)pf->l=pl;
		else
			pf->r=pl;
	}
	pl->f=pf;
	pl->r=t;
	t->f=pl; 
}
rbt * findfnode(int val){
	if(pRbt ==NULL) return NULL;
	rbt * t =pRbt;
	while(1)
	{
		if(t->l && t->val >val)
			 t=t->l;
		if(t->r&& t->val <val)
			 t=t->r;
		if((t->l==NULL && t->val >val)||(t->r==NULL && t->val <val))
			  break;
	}
	return t; 
}
rbt * GetUncle(rbt *  p ){
	rbt* gf = p->f->f;
	rbt* uncle;
	if(gf->l == p->f) uncle = gf->r;
	else uncle = gf->l;
	return uncle;
}
void insert(int val){
	if(pRbt == NULL) {
		pRbt =createNode(val);
		pRbt->color =black ;
		return ;
	}
	rbt * t = createNode(val);
	rbt * f = findfnode(val);
	rbt * gf, *uncle ;
	if(f->val >t->val)
	{
		t->f=f;
		f->l= t;
	}
	else
	{
		t->f=f;
		f->r=t;
	}
	//連接上以後判斷情況 
	if(f->color == black)
		return;
	//父節點爲紅色 看叔叔節點
	while(f->color ==red)
	{
		gf =f->f;
		if(gf==NULL) return;
		uncle = GetUncle(t) ;

		//如果叔叔是紅色
		if(uncle && uncle->color==red)
		{
			f->color =black;
			uncle->color =black;
			gf->color=red;
			if(gf==pRbt)
			{
				gf->color=black;
				return ;
			}
			t=f;
			f=gf;
			continue;
		}
		//叔叔是黑色 
		if(uncle==NULL || uncle->color ==black)
		{
			gf = f->f;
			if(gf->l==f)
			{ 
				if(t=f->l)
				{
					//父黑祖父紅
					f->color=black;
					gf->color =red;
					 rightTurn(&f);
					return ; 
				}
				else
				{
					 t=f; 
					 leftTurn(&f);
					 f=t->f;
					continue; 
				} 
			}
			else
			{
				gf = f->f;
				if(t=f->l)
				{
					t=f;
					 rightTurn(&t);
					f=t->f;
					return ;
				}
				else
				{
					f->color=black;
					gf->color =red;
					 leftTurn(&gf);
					return;
				}
			}
		} 
	}
}
void print(rbt * pRbt)
{
	if(pRbt ==NULL) return ;
	printf("%d ===  %d  \n",pRbt->val ,pRbt->color);
	print(pRbt->l);
	print(pRbt->r);
}
void build (int * a,int n){
	if(a==NULL||n<=0)return ;
	f(i,0,n-1)
	{
		insert(a[i]);
	//	print(pRbt);
	}
}
rbt * select_node(int val){
	if(pRbt ==NULL) return NULL;
	rbt * t =pRbt;
	while(1)
	{
		if(t->l && t->val >val)
			 t=t->l;
		if(t->r&& t->val <val)
			 t=t->r;
		if(t->val ==val )return t;
	}
	return NULL; 
}

 rbt *GetBrother(rbt * t)
 {
	 if(t==NULL)return NULL;
	 if(t->f->l ==t)return t->f->r;
	 else return t->f->l;
 }
void delnode(int val){
	rbt * t = select_node(val);
	if(t==NULL) return ;
	
	rbt *pMark =NULL; 
	rbt *pf ;
	//有兩個孩子 
	if(t->l && t->r)
	{
		rbt * d = t->l;
		while(d->r)d=d->r;
		d->f->r=NULL;
		t->val = d->val;
		pMark =d; 
	}
	//1.根沒有孩子 或者 2 根有一個孩子
	if(t==pRbt &&(t->l==NULL&&t->r==NULL)||(t->l&&t->r==NULL)||(t->r&&t->l==NULL))
	{
		pRbt = t->l?t->l:t->r;
		pMark = t;
	}
	//紅色節點
	if(t->color ==red)
	{
		pf=t->f;
		if(pf->l==t)
			pf->l =NULL;
		else
			pf->r=NULL;
		return ;
	}
	// 黑色 有一個紅孩子
	if(t->color==black && (t->l&&t->r==NULL) ||(t->r&&t->l==NULL))
	{
		if(t->l) 
		{
			t->val=t->l->val;
			pMark =t->l;
			t->l=NULL;
		}
		else
		{
			t->val=t->r->val;
			pMark =t->r;
			t->r=NULL;
		}
	}


	//黑色沒有孩子 看兄弟
	pf=t->f;
	rbt * pb =GetBrother(t);
	pMark =t;
	if(pf->l==t)
		pf->l=NULL;
	else pf->r=NULL;

	while(1)
	{
		//兄弟是紅的 染黑旋轉
		if(pb && pb->color==red)
		{
			pb->color=black;
			pf->color=red;
			if(pb=pf->l){
				pb=pb->r;
				rightTurn(&pf);
				continue;
			}
			else 
			{
				pb=pb->r;
				leftTurn(&pf);
				continue;
			}
		}
		//兄弟是黑的
		if(pb && pb->color==black)
		{
			//兩個侄子都是黑的
			if(pb->l&&pb->r || (pb->l&&pb->r==NULL) || (pb->r&&pb->l==NULL)	)
			{
				pb->color = red;
				if(pf->color==red)
				{
					pf->color=black;
					break;
				}
				else
				{
					t=pf;
					pf=t->f;
					if(pf==NULL) break;
					pb=GetBrother(t);
					continue;
				}
			}
			//佐侄子 紅 右黑 
			if(pb ->l && pb->l->color==red && pb->r==NULL|| pb->r->color==black)
			{
				if(pb=pf->r)
				{
					pb->color=red;
					pb->l->color=black;
					rightTurn(&pb);
					pb=GetBrother(t);
					continue;
				}
				else
				{
					pb->color=pf->color;
					pb->l->color=black;
					pf->color=black;

					rightTurn(&pf);
					break;
				}
			}
			//右侄子是紅色
			if(pb->r &&pb->r->color==red)
			{
				if(pb==pf->r)
				{
					pb->color=pf->color;
					pf->color=black;
					pb->r->color=black;
					leftTurn(&pf);
					break;
				}
				else
				{
					pb->r->color=black;
					pb->color=red;
					leftTurn(&pb);
					pb=pb->f;;
					continue;
				}
			} 
		}
	}
	 

	free(pMark);
	pMark=NULL;



}

int main(){
	int a[]={2,4,9,45,61,3,1 };
	int n = sizeof(a)/sizeof(a[0]);
	build(a,n);
	 
	print(pRbt);

	return 0;

}


發佈了59 篇原創文章 · 獲贊 3 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章