红黑树有以下的性质:
性质1. 节点是红色或黑色。
性质2. 根节点是黑色。
性质3 每个叶节点(NIL节点,空节点)是黑色的。
性质4 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
性质5. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
红黑树是二叉平衡树的一种、STL中的map、set、xxxmap、xxxset都是使用红黑树来完成的。它可以在O(log n)时间内做查找,插入和删除,这里的n 是树中元素的数目。
我就不画图了,网上可以搜到很多:红黑树删除操作
插入操作
回到正题:先开始插入操作(不要紧张、让我们慢慢将它理清)
X当前要插入的节点、P父亲、G祖父、GG曾祖、S叔叔:(新节点都是红色的)
情况一:根节点为空
X直接成为根节点、改变颜色为黑。
情况二:P为黑色
X直接插入、什么也不用做
情况三:P为红色
1.S为黑色
1.1 X为外侧插入:改变P G颜色 G旋转
P为G左、X为P左 : G右旋(当然是改变颜色之后)
P为G右、X为P右 : G左旋
1.2 X为内侧插入:P 旋转 改变X G颜色 G旋转(为什么这次改变的是X的颜色而不是P、因为旋转后X就会到达上面P的位置、说白了内侧插入的处理方式就是将其转化成外侧插入再处理。)
P为G左、X为P右 : P 左旋 变颜色 G右旋
P为G右、X为P左 : P 右旋 变颜色 G左旋
2.S为红色
2.1 X为外侧插入:G旋转 改变X颜色
P为G左、X为P左 :G右旋
P为G右、X为P右 :G左旋
2.2 X为内侧插入:P X旋转、改变P颜色、G旋转
P为G左、X为P右 :P 左旋 变颜色 G右旋
P为G右、X为P右 :P 右旋 变颜色 G左旋
注意:当S为红色时、在进行上面所说的操作之后、要进行判断、如果GG( 要注意旋转之后节点之间关系的变化 )为红色则以当前这棵小树的根节点为X重新判定。
掌握了关键的判定点整个插入操作就有了框架、至于没有图。。。自己去搜吧(有很多、对照着看)
其实插入还是比较简单的、很多情况的处理方法都差不多、内侧插入的情况都是先转化为外侧情况 再做的。
我直接把删除也说了吧、然后代码一起贴上
删除操作
X 要删除节点、P父亲、G祖父、S兄弟、N原节点
N原节点:在删除节点的时候、都会选择key对应位置的节点的右子树中最小的节点F(右子树的最左侧)或左子树中最大的节点E(左子树的最右侧)来替换当前key对应的节点、实际上删除的是F/E、将F/E的value赋给N节点、这里N就是原节点、而X是真正删除的节点。
情况一:X为根节点
直接删除、根节点赋空
情况二:X为红色节点
如果它是红色节点一定没有孩子的、直接删除 (别忘了对N进行赋值和对应位置赋空(它父亲的这个孩子没了 要赋空))
情况三:X为黑色节点
1.X有一个红孩子(不需考虑其他情况、如果有孩子、只能是一个、只能是红色、这是红黑树性质决定的)
用红孩子节点替换X的位置( 是替换、将X节点摘除 )、赋值给N、删除X
2.X没有孩子:X是一个黑色叶子节点
2.1 S为黑色
2.1.1 S有一个红孩子(先判断外侧孩子、如果外侧孩子不是红色、则将内侧孩子旋转成外侧的)
X为P左、侄为S右:P S颜色互换、侄变黑、左旋P、删除、结束
X为P右、侄为S左: 右旋P、
X为P左、侄为S左:S 侄 颜色互换、右旋S 情况转到上面
X为P右、侄为S右: 左旋S
2.1.2 S没有孩子:S是一个黑色叶子节点
P为红:P S 颜色互换、删除、结束
P为黑:S 变红 、直接删除、结束
2.2 S为红色
P S 颜色互换
X为P左:左旋P
X为P右:右旋P
注意:在操作时、不要忘记将N进行赋值、和对删除位置的替换或赋空。
下面见代码:
我将所有操作封在一个类中、插入删除操作重点看insert_cal()、erase()
一些操作确实复杂、但是红黑树值得我们 沉下心来 认真学习
#pragma once
#include <cstdio>
#include <cstdlib>
#include <string>
using namespace std;
template<class KEY,class VAL>
class CMyRBTree
{
private:
struct RBT
{
KEY key;
VAL value;
char color;
RBT* parent;
RBT* lchild;
RBT* rchild;
RBT(KEY k,VAL v):key(k),value(v),color('r'),parent(0),
lchild(0),rchild(0){}
};
RBT* root;
public:
CMyRBTree(void);
~CMyRBTree(void);
private:
void rotate_node_left(RBT* node); //左旋
void rotate_node_right(RBT* node); //右旋
void insert_cal(RBT* node); //插入节点后需要进行调整
RBT* _find(KEY key); //查找
void _release(RBT** root); //使用后序递归删除所有节点
void truncateNode(RBT* node); //对要删除节点的对应位置赋空
void deleteNode(RBT** node,RBT* top); //删除节点、对原节点赋值
public:
bool insert(KEY key,VAL val);
bool erase(KEY key);
bool find(KEY key,VAL& val);
bool release();
};
template<class KEY,class VAL>
CMyRBTree<KEY,VAL>::CMyRBTree(void):root(0)
{
}
template<class KEY,class VAL>
CMyRBTree<KEY,VAL>::~CMyRBTree(void)
{
release();
}
template<class KEY,class VAL>
void CMyRBTree<KEY,VAL>::rotate_node_left(RBT* node)
{
if(node == NULL || root == NULL)
return;
RBT* mark = node->rchild;
if(node->parent){
if(node == node->parent->lchild)
node->parent->lchild = mark;
else
node->parent->rchild = mark;
}else{//node为根节点、所以要对根节点指针重新赋值
root = mark;
root->color = 'b';
}
mark->parent = node->parent;
node->parent = mark;
node->rchild = mark->lchild;
mark->lchild = node;
if(node->rchild)
node->rchild->parent = node;
}
template<class KEY,class VAL>
void CMyRBTree<KEY,VAL>::rotate_node_right(RBT* node)
{
if(node == NULL || root == NULL)
return;
RBT* mark = node->lchild;
if(node->parent){
if(node == node->parent->lchild)
node->parent->lchild = mark;
else
node->parent->rchild = mark;
}else{
root = mark;
root->color = 'b';
}
mark->parent = node->parent;
node->parent = mark;
node->lchild = mark->rchild;
mark->rchild = node;
if(node->lchild)
node->lchild->parent = node;
}
template<class KEY,class VAL>
void CMyRBTree<KEY,VAL>::insert_cal(RBT* node)
{
if(node == NULL)
return;
RBT* ptmp = NULL; //叔叔
while(1)
{
if(node->parent == NULL){//根节点为空
node->color = 'b';
root = node;
break;
}
if(node->parent->color == 'b'){//父节点为红色直接插入
break;
}else{
if(node->parent->parent->lchild == node->parent)
ptmp = node->parent->parent->rchild;
else
ptmp = node->parent->parent->lchild;
if(ptmp == NULL || ptmp->color == 'b')
{//S为黑色
if(node->parent == node->parent->parent->lchild)
{//P是G的左孩子
if(node == node->parent->lchild)
{//X是P的左孩子
node->parent->color = 'b';
node->parent->parent->color = 'r';
rotate_node_right(node->parent->parent);
break;
}else{//X是P的右孩子
node->color = 'b';
node->parent->parent->color = 'r';
rotate_node_left(node->parent);
rotate_node_right(node->parent);
break;
}
}else{//P是G的右孩子
if(node == node->parent->rchild)
{//X是P的右孩子
node->parent->color = 'b';
node->parent->parent->color = 'r';
rotate_node_left(node->parent->parent);
break;
}else{//X是P的左孩子
node->color = 'b';
node->parent->parent->color = 'r';
rotate_node_right(node->parent);
rotate_node_left(node->parent);
break;
}
}
}
else
{//S节点为红色
if(node->parent == node->parent->parent->lchild)
{//P是G的左孩子
if(node == node->parent->lchild)
{
node->color = 'b';
rotate_node_right(node->parent->parent);
//调整节点重新判定
node = node->parent;
}else{
node->parent->color = 'b';
rotate_node_left(node->parent);
rotate_node_right(node->parent);
}
}else{
if(node == node->parent->rchild)
{
node->color = 'b';
rotate_node_left(node->parent->parent);
node = node->parent;
}else{
node->parent->color = 'b';
rotate_node_right(node->parent);
rotate_node_left(node->parent);
}
}
}
}
}
}
template<class KEY,class VAL>
bool CMyRBTree<KEY,VAL>::insert(KEY key,VAL val)
{
RBT* node = new RBT(key,val);
if(root == NULL)
{
root = node;
root->color = 'b';
return true;
}
RBT* ptmp = root;
while(1)
{
if(key > ptmp->key)
{
if(ptmp->rchild)
ptmp = ptmp->rchild;
else{
ptmp->rchild = node;
node->parent = ptmp;
insert_cal(node);
break;
}
}else if(key < ptmp->key)
{
if(ptmp->lchild)
ptmp = ptmp->lchild;
else{
ptmp->lchild = node;
node->parent = ptmp;
insert_cal(node);
break;
}
}else{//这里重复插入则、只改变value值
ptmp->value = val;
delete node;
node = NULL;
break;
}
}
return true;
}
template<class KEY,class VAL>
void CMyRBTree<KEY,VAL>::truncateNode(RBT* node)
{
if(node && node->parent){
if(node == node->parent->lchild)
node->parent->lchild = NULL;
else
node->parent->rchild = NULL;
}
}
template<class KEY,class VAL>
void CMyRBTree<KEY,VAL>::deleteNode(RBT** node,RBT* top)
{
if(*node == NULL)
return;
if(top){
top->key = (*node)->key;
top->value = (*node)->value;
}
delete *node;
*node = NULL;
}
template<class KEY,class VAL>
bool CMyRBTree<KEY,VAL>::erase(KEY key)
{
RBT* node = _find(key);
if(node == NULL)
return false;
RBT* ptmp = NULL;
if(node->rchild){
ptmp = node->rchild;
if(ptmp->lchild)
while(ptmp->lchild->lchild)
ptmp = ptmp->lchild;
}else if(node->lchild){
ptmp = node->lchild;
if(ptmp->rchild)
while(ptmp->rchild->rchild)
ptmp = ptmp->rchild;
}else{//node原节点是叶子节点
ptmp = node;
}
//删除根节点
if(ptmp->parent == NULL){
deleteNode(&ptmp,NULL);
root = NULL;
}
RBT* pbrother = NULL; //兄弟节点
if(ptmp == ptmp->parent->lchild)
pbrother = ptmp->parent->rchild;
else
pbrother = ptmp->parent->lchild;
while(1)
{
if(ptmp->color == 'r')
{//X为红色
truncateNode(ptmp);
deleteNode(&ptmp,node);
break;
}else{//X为黑色节点
if(ptmp->lchild || ptmp->rchild)
{//有一个红孩子(如果有,只能有一个孩子、也只能是红色)
if(ptmp->lchild){
ptmp->lchild->color = 'b';
ptmp->lchild->parent = ptmp->parent;
if(ptmp == ptmp->parent->lchild)
ptmp->parent->lchild = ptmp->lchild;
else
ptmp->parent->rchild = ptmp->lchild;
deleteNode(&ptmp,node);
break;
}else{
ptmp->rchild->color = 'b';
ptmp->rchild->parent = ptmp->parent;
if(ptmp == ptmp->parent->lchild)
ptmp->parent->lchild = ptmp->rchild;
else
ptmp->parent->rchild = ptmp->rchild;
deleteNode(&ptmp,node);
break;
}
}else
{//X为黑色叶子节点/此时pbrother节点一定不为空
if(pbrother->color == 'b')
{//兄弟节点为黑色
if((pbrother->rchild && pbrother->rchild->color == 'r')
||(pbrother->lchild && pbrother->lchild->color == 'r'))
{//S至少有一个红孩子
if(pbrother->rchild &&
pbrother->rchild->color == 'r')
{
if(ptmp == ptmp->parent->lchild){
pbrother->color = ptmp->parent->color;
ptmp->parent->color = 'b';
pbrother->rchild->color = 'b';
rotate_node_left(ptmp->parent);
truncateNode(ptmp);
deleteNode(&ptmp,node);
break;
}else{
pbrother->color = 'r';
pbrother->rchild->color = 'b';
rotate_node_left(pbrother);
if(ptmp == ptmp->parent->lchild)
pbrother = ptmp->parent->rchild;
else
pbrother = ptmp->parent->lchild;
//进入下一次判定
}
}else{
if(ptmp == ptmp->parent->rchild)
{
pbrother->color = ptmp->parent->color;
ptmp->parent->color = 'b';
rotate_node_right(ptmp->parent);
truncateNode(ptmp);
deleteNode(&ptmp,node);
break;
}else{
pbrother->color = 'r';
pbrother->lchild->color = 'b';
rotate_node_right(pbrother);
if(ptmp == ptmp->parent->lchild)
pbrother = ptmp->parent->rchild;
else
pbrother = ptmp->parent->lchild;
//进入下一次判定
}
}
}else{//
if(pbrother->lchild == NULL && pbrother->rchild == NULL)
{//S为黑色叶子节点
if(ptmp->parent->color == 'r')
{//P为红色
pbrother->color = ptmp->parent->color;
ptmp->parent->color = 'b';
truncateNode(ptmp);
deleteNode(&ptmp,node);
break;
}else{
pbrother->color = 'r';
truncateNode(ptmp);
deleteNode(&ptmp,node);
break;
}
}
}
}
//S节点为红色
else
{
pbrother->color = ptmp->parent->color;
ptmp->parent->color = 'r';
if(ptmp == ptmp->parent->lchild){
rotate_node_left(ptmp->parent);
}else{
rotate_node_right(ptmp->parent);
}
//调整pbrother指针、进入下一次判定
if(ptmp == ptmp->parent->lchild)
pbrother = ptmp->parent->rchild;
else
pbrother = ptmp->parent->lchild;
}
}
}
}
return true;
}
template<class KEY,class VAL>
typename CMyRBTree<KEY,VAL>::RBT* CMyRBTree<KEY,VAL>::_find(KEY key)
{
if(root == NULL)
return NULL;
RBT* ptmp = root;
while(1)
{
if(key > ptmp->key)
{
if(ptmp->rchild)
ptmp = ptmp->rchild;
else
return NULL;
}else if(key < ptmp->key)
{
if(ptmp->lchild)
ptmp = ptmp->lchild;
else
return NULL;
}else
return ptmp;
}
return NULL;
}
template<class KEY,class VAL>
bool CMyRBTree<KEY,VAL>::find(KEY key,VAL& val)
{
RBT* node = _find(key);
if(node == NULL)
return false;
val = node->value;
return true;
}
template<class KEY,class VAL>
void CMyRBTree<KEY,VAL>::_release(RBT** root)
{
if(*root == NULL)
return ;
_release(&(*root)->lchild);
_release(&(*root)->rchild);
delete *root;
*root = NULL;
}
template<class KEY,class VAL>
bool CMyRBTree<KEY,VAL>::release()
{
_release(&root);
return true;
}
文章如有错误之处、欢迎指正。。。