紅黑樹: 一個平衡的二叉樹,但不是一個完美的平衡二叉樹。 查找在~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; }