一、什么事RBtree:
所谓的红黑树它需要满足一下条件:
1、该树是一颗二叉搜索树(搜索树就是按照节点值大小进行排序插入,中序就是所有节点的从小到大排序)
2、每个节点不是红色就是黑色
3、根节点为黑色
4、红节点不相连
5、任一节点至NULL(树尾)的任何途径,所含之黑节点树必须相同
为了统一,我们视NULL为黑节点。
红黑树的有点就在于它没有平衡因子,唯一需要让它调整的就是新节点的颜色,在数据插入上大大减少了调整次数。
我们来简单的看一组数据组成的个红黑树的模型:
{100,80,60,40,50,75,73,72,74}
新节点的颜色我们设为红色,我们把新的节
上图是模型红黑树调整的全过程,蓝色箭头代表的是平衡的红黑树有的是新节点的插入,红箭头代表对新插入节点导致不平衡的调整平衡过程。
二、RBTree是怎么实现的:
树的操作再前面刚开始学二叉树的时候相信你已经有所掌握,bst、avl、rbt树都一样,这三中树最重要的操作就是增加节点和删除节点,在这里我也只对节点的增加进行代码分析,在红黑树下篇会对其节点的删除代码进行分析,下面就是RBtree的增加节点代码展示:
#pragma once
template<class Type>
class RBTree;
typedef enum{RED = 0, BLACK = 1}COLOR;
template<class Type>
class RBNode
{
friend class RBTree<Type>;
public:
RBNode():data(Type()),leftchild(NULL),rightchild(NULL),color(0),parent(NULL)
{}
RBNode(Type d = Type(), RBNode<Type>* left = NULL, RBNode<Type>* right = NULL, RBNode<Type>* pr = NULL, COLOR c = RED):data(d), parent(pr),leftchild(left),rightchild(right),color(c)
{}
private:
COLOR color;
Type data;
RBNode<Type>* parent;
RBNode<Type>* leftchild;
RBNode<Type>* rightchild;
};
template<class Type>
class RBTree
{
public:
RBTree():root(NULL)
{}
public:
bool Insert(const Type & x)
{
return Insert(root, x);
}
protected:
bool Insert(RBNode<Type>* &t, const Type &x)
{
RBNode<Type>* p = t;
RBNode<Type> *pr = NULL;
while(p != NULL)
{
if(x == p->data)
return false;
pr = p;
if(x < p->data)
p=p->leftchild;
else
p = p->rightchild;
}
p = _Buynode(x);
if(pr == NULL)
{
p ->color = BLACK;
t = p;
return true;
}
if( x < pr->data)
pr->leftchild = p;
else
pr ->rightchild = p;
p->parent = pr;
_Balance_Tree(t,p);
return true;
}
protected:
//这里的调整方法比较复杂,代码最下面有优化代码,仔细阅读世界独有,走马观花竹篮打水
void _Balance_Tree(RBNode<Type>* &t, RBNode<Type>* q)
{
while(q->parent != NULL && q->parent->color == RED)//p->parent != NULL 是为了保证循环条件成立不会造成程序的崩溃,提高了程序的严谨性
{
RBNode<Type> * s =NULL;
if(q->parent->parent!=NULL && q->parent->parent->leftchild == q->parent)
{
s = q->parent->parent->rightchild;
if((q == q->parent->leftchild && s==NULL) || q == q->parent->leftchild &&s!=NULL && s->color==BLACK)// /
{
q->parent ->color = BLACK;
q->parent->parent -> color = RED;
if(s != NULL)
s->color = RED;
RotateR(q->parent->parent);
}
else if((q == q->parent->rightchild && s==NULL) || q == q->parent->rightchild &&s!=NULL && s->color==BLACK)// /
{
q->parent->parent->color = RED;
q->color = BLACK;
RotateLR(q->parent->parent);
}
else if(q == q->parent->leftchild && s->color == RED)
{
q->color = BLACK;
RotateR(q->parent->parent);
if(q->parent->parent!= NULL && q->parent->parent->color == RED)
{
q = q->parent;
continue;
}
else
break;
}
else if(q == q->parent->rightchild && s->color == RED)
{
q->parent->color = BLACK;
RotateLR(q->parent->parent);
if(q->parent != NULL && q->parent->color == RED)
{
q=q->parent;
continue;
}
else
break;
}
}
else
{
s = q->parent->parent->leftchild;
if((q == q->parent->leftchild && s==NULL) || q == q->parent->leftchild &&s!=NULL && s->color==BLACK)// /
{
q ->color = BLACK;
q->parent->parent->color = RED;
RotateRL(q->parent->parent);
else if((q == q->parent->rightchild && s==NULL) || q == q->parent->rightchild &&s!=NULL && s->color==BLACK)// /
{
q->parent->parent->color = RED;
q->parent->color = BLACK;
if(s != NULL)
s->color = RED;
RotateL(q->parent->parent);
}
else if(q == q->parent->leftchild && s->color == RED)
{
q->parent->color = BLACK;
RotateRL(q->parent->parent);
if(q->parent->parent->color == BLACK)
break;
else
{
q = q->parent;
continue;
}
}
else if(q == q->parent->rightchild && s->color == RED)
{
q->parent->color = BLACK;
RotateL(q->parent->parent);
if(q->parent->color == RED)
{
q=q->parent;
continue;
}
else
break;
}
}
}
t->color = BLACK;
}
protected:
RBNode<Type>* RotateR(RBNode<Type> *ptr)
{
RBNode<Type> * subR = ptr;
ptr = subR->leftchild;
subR->leftchild = ptr->rightchild;
if(ptr->rightchild != NULL)
ptr->rightchild ->parent = subR;
ptr->rightchild = subR;
if(subR->parent == NULL)
root = ptr;
else
{
if(subR == subR->parent->leftchild)
subR->parent->leftchild = ptr;
else
subR->parent->rightchild = ptr;
}
ptr->parent = subR->parent;/////////
subR->parent = ptr;
return ptr;
}
void RotateL(RBNode<Type>* ptr)
{
RBNode<Type>* subL = ptr;
ptr = subL->leftchild;
subL->rightchild = ptr->leftchild;
if(ptr->leftchild != NULL)
ptr->leftchild->parent = subL;
if(subL->parent == NULL)
root = ptr;
else
{
if(subL == subL->parent->leftchild)
subL->parent->leftchild = ptr;
else
subL->parent->rightchild = ptr;
}
ptr->parent = subL->parent;
subL->parent = ptr;
}
void RotateRL(RBNode<Type>* ptr)
{
RBNode<Type>* subR = ptr->rightchild;
RBNode<Type>* subL = ptr;
ptr = subR->leftchild;
subR->leftchild = ptr->rightchild;
if(ptr->rightchild != NULL)
ptr->rightchild->parent = subR;
ptr->rightchild = subR;
subL->rightchild = ptr->leftchild;
if(ptr->leftchild != NULL)
ptr->leftchild->parent = subL;
ptr->leftchild = subL;
if(subL->parent == NULL)
root = ptr;
else
{
if(subL == subL->parent ->leftchild)
subL->parent ->leftchild = ptr;
else
subL->parent->rightchild = ptr;
}
ptr->parent = subL->parent;
subL->parent = ptr;
subR->parent = ptr;
}
void RotateLR(RBNode<Type>* ptr)
{
RBNode<Type>* subR = ptr;
RBNode<Type>* subL = ptr->leftchild;
ptr = subL->rightchild;
subL->rightchild = ptr->leftchild;
if(ptr->leftchild != NULL)
ptr->leftchild ->parent = subL;
ptr->leftchild = subL;
subR->leftchild = ptr->rightchild;
if(ptr->rightchild != NULL)
ptr->rightchild->parent = subR;
ptr->rightchild = subR;
if(subR->parent == NULL)
root = ptr;
else
{
if(subR == subR->parent->leftchild)
subR->parent->leftchild = ptr;
else
subR->parent->rightchild = ptr;
}
ptr->parent = subR->parent;
subL->parent = ptr;
subR->parent = ptr;
}
private:
RBNode<Type>* _Buynode(const Type x)
{
RBNode<Type>* new1 = new RBNode<Type>(x);
return new1;
}
private:
RBNode<Type>* root;
};
三、对于平衡调整的代码优化:
对与调整的模块的优化:
/*优化说明:在节点插入的同时,我们需要考虑其伯父节点是否存在,如果存在我们看其伯父节点是否为红色,如果是只需要将伯父节点和父节点的颜色改为黑色并把祖父节点颜色调为红色,改为在树中插入祖父节点来向上调整即可,这里优化的还有我们最多只需要对节点进行两次单旋转即可达到目的*/
void _Balance_Tree(RBNode<Type>* &t, RBNode<Type>* q)
{
while(q->parent->color == RED)
{
RBNode<Type> * s =NULL;
if(q->parent->parent!=NULL && q->parent->parent->leftchild == q->parent)
{
s = q->parent->parent->righthchild;
if( s != NULL && s->color = RED)
{
q->parent->color = BLACK;
s -> color = BLACK;
q->parent->parent->color = RED;
q = q->parent;
continue;
}
else if(q = q->parent->rightchild)
{
q = q->parent;///////////为下面单转做铺垫
RotateL(q);
}
q->parent->color = BLACK;
q->parent->parent = RED;
RotateR(q->parent->parent);
}
else
{
if(q->parent->parent!=NULL && q->parent->parent->leftchild == q->parent)
{
s = q->parent->parent->lefthchild;
if( s != NULL && s->color = RED)
{
q->parent->color = BLACK;
s -> color = BLACK;
q->parent->parent->color = RED;
q = q->parent->parent;
continue;
}
else if(q == q->parent->leftchild)
{
q = q->parent;
RotateR(q);
}
q->parent->color = BLACK;
q->parent->parent = RED;
RotateL(q->parent->parent);
}
}
}
如果你认真阅读了博客,相信你已经对红黑树有了一定的了解,自己亲手编程将会让你能够掌握红黑树节点的增加。在普通调整和优化后的调整两种方法调整得到的最终红黑树的结果是不相同的,但是经过调整后的红黑树任然正确。还是那句话走马观花竹篮打水,仔细阅读世界独有。