紅黑樹演算法的思想與實現(一)
紅黑樹 是一顆二叉搜尋樹:樹中每一個節點不是黑色就是紅色。可以把一顆紅黑樹視為一顆擴充二叉樹,用外部節點表示空指標。。。
有如下特性:
1.根節點和所有外部節點的顏色是黑色。
2.從根節點到外部節點的途中沒有連續兩個節點的顏色是紅色。
3.所有從根節點到外部節點的路徑上都有相同數目的黑色節點。
一、紅黑樹的搜尋
對普通二叉搜尋樹進行搜尋的時間複雜度為O(h), 對於紅黑樹則為O(lg n)--《以2為底n的對數》;
最差情況下AVL樹的時間複雜度最優。
二、紅黑樹的插入
首先使用二叉搜尋樹的插入演算法將一個元素插入到紅黑樹中,在插入過程中需要為其染色。
①、如果插入前是是空樹,那麼新元素將成為根節點,根據特徵1,根節點必須染成黑色。
②、如果插入前樹非空,若新節點被染成黑色,將違反紅黑樹特性3,所有從根到外部節點的路徑上的黑色節點個數不等。因此 新插入節點將被染成紅色,但這又可能違反紅黑樹的特性2,出現連續兩個紅色節點,因此需要重新平衡。
設新插入節點為u, 它的父節點和祖父節點分別為pu,gu,
②.1 若pu是黑色節點,則特性2沒有被破壞,結束重新平衡的過程。
若pu是紅色節點,則出現連續兩個紅色節點的情形,這時考察pu的兄弟節點
②.2.1pu的兄弟節點gr是紅色節點, 此時gu為黑色,它有兩個紅色節點。交換節點gu和它的兩個子女的顏色,將可能破壞紅黑樹特性2,
因此需先判斷判斷gu是否為根節點,若不是根節點,則交換gu與它的兩個子女顏色;若gu是根節點,則只需將兩個子女節點的顏色變為gu的顏色,而gu顏色無需改變。
②.2.2 pu的兄弟節點為黑色,此時又有兩種情況。
---1>pu是gu的左子女,u是pu的 左子女。 ---->交換pu和gu的顏色,做一次右單旋轉
u是pu的右子女。 ---->先交換u和gu的顏色,再左旋轉,再右旋轉。
---2>pu是gu的右子女,u是pu右子女。 ---->交換pu和gu的顏色,做一次左單旋轉
u是pu的左子女。 ---->先交換u和gu的顏色,左旋轉,右旋轉
總歸紅黑樹插入這麼分 :1、黑父, 2、紅父, 2.1、紅叔, 2.2、黑叔。
#include<iostream> #include<assert.h> using namespace std; typedef int Type; typedef enum Color{RED,BLACK}; typedef struct RBNode { Type data; Color color; struct RBNode *leftChild; struct RBNode *rightChild; struct RBNode *parent; }RBNode; typedef struct RBTree { RBNode *root; RBNode *nul; }RBTree; RBNode* buynode() { RBNode *s = new RBNode; assert(s != NULL); memset(s,0,sizeof(RBNode)); return s; } void InitRBTree(RBTree &t) { t.nul = buynode(); t.root = t.nul; t.nul->color = BLACK; t.nul->data = -1; } void RotateR(RBTree &t,RBNode *x) //右轉,將根節點變為x的左子樹節點 { RBNode *subR = x; x = subR->leftChild; subR->leftChild = x->rightChild; if(x->rightChild != t.nul) x->rightChild->parent = subR; x->rightChild = subR; if(subR->parent == t.nul) { t.root = x; } else if(subR == subR->parent->leftChild) subR->parent->leftChild = x; else subR->parent->rightChild = x; x->parent = subR->parent; subR->parent = x; } void RotateL(RBTree &t, RBNode *x) //根節點變為x的右子樹 { RBNode *subL = x; x = subL->rightChild; subL->rightChild = x->leftChild; if(x->leftChild != t.nul) x->leftChild->parent = subL; x->leftChild = subL; if(subL->parent == t.nul) t.root = x; else if(subL->parent->rightChild == subL) subL->parent->rightChild = x; else subL->parent->leftChild = x; x->parent = subL->parent; subL->parent = x; } void insert_rebalance(RBTree &t, RBNode *u) { u->color = RED; RBNode *pu = u->parent; RBNode *gu = pu->parent; while(u!=t.root && pu->color==RED) { if(gu->leftChild == pu) { if(gu->rightChild && gu->rightChild->color == RED) //pu的兄弟節點存在且是紅色 { //此時gu是黑色,他有兩個紅色子女節點 //交換gu和其兩個子女的顏色 gu->rightChild->color = BLACK; pu->color = BLACK; if(gu->data != t.root->data) gu->color = RED; } else //pu的兄弟節點顏色為黑色 { if(pu->leftChild == u) //u、pu、gu都在一條左子樹上 {//交換pu、gu的顏色 pu->color = BLACK; gu->color = RED; RotateR(t,gu); } else { gu->color = RED; u->color = BLACK; RotateL(t,pu); RotateR(t,gu); return; } } } else //gu->rightChild == pu { if(gu->leftChild && gu->leftChild->color == RED) //交換gu和其兩個子女的顏色 { gu->leftChild->color = BLACK; pu->color = BLACK; if(gu->data != t.root->data) gu->color = RED; } else //pu的兄弟節點顏色為黑色 { if(pu->leftChild == u) { gu->color = RED; u->color = BLACK; RotateR(t,pu); RotateL(t,gu); return; } else { gu->color = RED; pu->color = BLACK; RotateL(t,gu); } } } } t.root->color = BLACK; return; } bool Insert(RBTree &t, const Type u) { RBNode *parent = t.nul; RBNode *p = t.root; while(p != t.nul) { if(t.root->data == u) return false; parent = p; if(parent->data < u) p = parent->rightChild; else p = parent->leftChild; } p = buynode(); p->data = u; p->color = RED; p->leftChild = t.nul; p->rightChild = t.nul; p->parent = t.nul; if(t.root == t.nul) { t.root = p; t.root->color = BLACK; return true; } if(parent->data > u) parent->leftChild = p; else parent->rightChild = p; p->parent = parent; insert_rebalance(t,p); return true; }
void remove_balance(RBTree &t, RBNode *p)
{
RBNode *u;
RBNode *g = p->parent;
RBNode *v = g->leftChild;
RBNode *w = v->leftChild;
RBNode *r = v->rightChild;
if(p->rightChild == t.nul) //兩種情況,1。p->leftChild!=t.nul 2.p->rightChild==t.nul
{
if(p->leftChild != t.nul)
{
u = p->leftChild;
if(p->color == RED)
{
g->rightChild = u;
}
else
{
if(u->color == RED)
u->color = BLACK;
g->rightChild = u;
if(v->color == BLACK) //v是u的左兄弟
{
if(w && w->color==RED) //v的左子女為w
{
w->color = BLACK;
g->color = BLACK;
v->color = RED;
RotateR(t, g);
}
else
{
if(r && r->color == RED) //w的有兄弟節點r
{
g->color = BLACK;
RotateL(t, v);
RotateR(t, g);
}
else
{
if(g->color == RED)
{
g->color = BLACK;
v->color = RED;
}
else
{
RotateR(t, g);
}
}
}
}
else //v->color = RED
{
RBNode* s = r->leftChild;
if(s->color == RED)
{
RotateL(t, v);
RotateR(t, g);
}
else //s->color==BLACK
{
RBNode* q = r->rightChild;
if(q->color == RED)
{
RotateL(t,r);
RotateL(t, v);
RotateR(t, g);
}
else //q->color == BLACK
{
r->color = RED;
v->color = BLACK;
RotateR(t, v);
}
}
}
}
}
else //p->leftChild == t.nul && p->rightChild==t.nul
{
if(p == g->leftChild)
{
if(p->color == BLACK)
{
if(g->rightChild->color == RED)
{
}
}
g->leftChild = t.nul;
}
else
{
if(p->color == BLACK)
{
g->leftChild->color = BLACK;
g->color = RED;
RotateR(t, g);
}
g->rightChild = t.nul;
}
}
//freenode(p);
delete p;
}
else //p->rightChild != t.nul -->(p->leftChild==t.nul)
{
RBNode *pr=p->rightChild;
if(p->color == RED)
{
if(g->rightChild == p)
g->rightChild = pr;
else
g->leftChild = pr;
}
else //p->color==BLACK
{
}
}
}
bool Remove(RBTree &t,const Type& u)
{
RBNode *p = t.root;
while(p != t.nul)
{
if(p->data == u)
{
RBNode *tmp;
//調整
if(p->leftChild != t.nul && p->rightChild != t.nul)
{
//RBNode* l = p->leftChild;
tmp = p->rightChild;
while(tmp->leftChild != t.nul)
tmp = tmp->leftChild;
p->data = tmp->data;
remove_balance(t, tmp);
}
else //被刪節點只有一個子女或沒有子女
{
remove_balance(t, p);
}
return true;
}
if(p->data > u)
p = p->leftChild;
else
p = p->rightChild;
}
return false;
}
void visit(RBNode *t)
{
cout<<t->data<<"("<<t->color<<")"<<" ";
}
void Print(RBTree &t)
{
RBNode *p = t.root;
stack<RBNode*> st;
while(p!=t.nul || !st.empty())
{
if(p!=t.nul)
{
st.push(p);
p = p->leftChild;
}
else
{
p = st.top();
st.pop();
visit(p);
p = p->rightChild;
}
}
cout<<endl;
}
size_t size(RBTree &t)
{
RBNode *p = t.root;
stack<RBNode*> st;
int count = 0;
while(p!=t.nul || !st.empty())
{
if(p!=t.nul)
{
st.push(p);
p = p->leftChild;
}
else
{
p = st.top();
st.pop();
count++;
p = p->rightChild;
}
}
//cout<<count<<endl;
return count;
}
//main函式
#include "RBTree.h"
void main()
{
int a[] = {10,12,3,8,11,5,20,7,18};
RBTree rbt;
InitRBTree(rbt);
for(int i=0; i<(sizeof(a)/sizeof(int)); ++i)
{
Insert(rbt,a[i]);
}
Remove(rbt, 10);
Remove(rbt, 12);
Remove(rbt, 18);
Print(rbt);
cout<<size(rbt)<<endl;
}