红黑树与二叉查找树相似,只是增加了一个字段来表示节点是红色还是黑色。为什么要增加这个属性呢?在二叉查找树中,如果节点按照从大到小或从小到大插入,二叉查找树就变成了一个链表。因此增加这个字段来调整树的高度避免它变成一个链表,为什么能避免?
首先看一下红黑树的属性:
1. 每个节点非红即黑。
2. 根节点为黑色。
3. 每个叶子节点都为黑色。
4. 如果一个节点为红色,那么它的子女必须为黑色。
5. 任意节点到它子树叶子节点所有路径都必须包含相同黑色节点个数。
由此可得出定理:
A red-black tree with n internal nodes has height at most 2 lg(n + 1).
证明:存在任一个节点x,把x到达任一个叶子节点的路径中的黑节点的个数称为黑高度,设为bh(x)。首先证明x的子树中至少有2bh(x)-1个节点,用归纳法证明。根据x和他子女的红黑属性,可得出x子女的黑高度为bh(x)或bh(x)-1,可假设子女的子树至少有2bh(x)-1个节点,那么x就至少有2bh(x)-1-1+2bh(x)-1-1+1=2bh(x)-1个节点。设n>=2bh(x)-1,则bh(x)<=2lg(n+1)。因此红黑属性一定程度保证了树的平衡性。
红黑树实现:
红黑树的实现与二叉查找树的实现相似,只是在插入删除的时候加入调整函数以保证红黑树的属性。
RBTree.h:
//
RBTree.h
#pragma
once
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
typedef
enum
_color
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
RED,
BLACK
}
COLOR;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
class
RBNode
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
public:
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
RBNode(void):key(0),parent(NULL),left(NULL),right(NULL),color(BLACK)...{}
RBNode(int value);
public:
~RBNode(void);
public:
int key;
RBNode *parent;
RBNode *left;
RBNode *right;
COLOR color;
}
;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
class
RBTree
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
public:
RBTree(void);
void Insert(int value);
void Delete(int value);
RBNode* Max(RBNode *pNode);
RBNode* Min(RBNode *pNode);
void Dispose(RBNode *pNode);
public:
~RBTree(void);
private:
void LeftRotate(RBNode *pNode);
void RightRotate(RBNode *pNode);
void InsertFixUp(RBNode *pNode);
RBNode* Successor(RBNode *pNode);
void DeleteFixUp(RBNode *pNode);
private:
RBNode* m_pRoot;
static RBNode *nil;
}
;
RBTree.cpp:
#include
"
StdAfx.h
"
#include
"
RBTree.h
"
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
RBNode::RBNode(
int
value)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
key=value;
parent=NULL;
left=NULL;
right=NULL;
color=RED;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
RBNode::
~
RBNode()
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
RBNode
*
RBTree::nil
=
new
RBNode();
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
RBTree::RBTree(
void
)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
m_pRoot=NULL;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
RBTree::
~
RBTree(
void
)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
Dispose(m_pRoot);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
void
RBTree::Dispose(RBNode
*
pNode)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
if(pNode->left!=nil)
Dispose(pNode->left);
if(pNode->right!=nil)
Dispose(pNode->right);
delete pNode;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
void
RBTree::Insert(
int
value)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
if(m_pRoot==NULL)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
RBNode *pNew=new RBNode();
pNew->key=value;
pNew->parent=nil;
pNew->left=nil;
pNew->right=nil;
m_pRoot=pNew;
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
RBNode *py;
RBNode *px=m_pRoot;
while(px!=nil)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
py=px;
if(value<px->key)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
px=px->left;
}
else if(value>px->key)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
px=px->right;
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
py=nil;
}
}
if(py!=nil)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
RBNode *pNew=new RBNode(value);
pNew->parent=py;
if(value<py->key)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
py->left=pNew;
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
py->right=pNew;
}
pNew->left=nil;
pNew->right=nil;
pNew->color=RED;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
if(py!=this->m_pRoot)
InsertFixUp(pNew);
}
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
void
RBTree::LeftRotate(RBNode
*
pNode)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
if(pNode->right!=nil)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
RBNode *y=pNode->right;
pNode->right=y->left;
if(nil!=y->left)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
y->left->parent=pNode;
}
y->parent=pNode->parent;
if(nil==pNode->parent)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
m_pRoot=y;
}
else if(pNode=pNode->parent->left)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
pNode->parent->left=y;
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
pNode->parent->right=y;
}
y->left=pNode;
pNode->parent=y;
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
void
RBTree::RightRotate(RBNode
*
pNode)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
if(nil!=pNode->left)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
RBNode *y=pNode->left;
pNode->left=y->right;
if(nil!=y->right)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
y->right->parent=pNode;
}
y->parent=pNode->parent;
if(nil==pNode->parent)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
m_pRoot=y;
}
else if(pNode->parent->left==pNode)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
pNode->parent->left=y;
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
pNode->parent->right=y;
}
y->right=pNode;
pNode->parent=y;
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
void
RBTree::InsertFixUp(RBNode
*
pNode)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
while(pNode->parent->color==RED)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
RBNode *py;
if(pNode->parent==pNode->parent->parent->left)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
py=pNode->parent->parent->right;
//Case 1: z's uncle y is red
if(py->color==RED)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
pNode->parent->color=BLACK;
py->color=BLACK;
pNode->parent->parent->color=RED;
pNode=pNode->parent->parent;
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
//Case 2: z's uncle y is black and z is a right child
if(pNode==pNode->parent->right)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
pNode=pNode->parent;
this->LeftRotate(pNode);
}
//Case 3: z's uncle y is black and z is a left child
pNode->parent->color=BLACK;
pNode->parent->parent->color=RED;
this->RightRotate(pNode->parent->parent);
}
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
py=pNode->parent->parent->left;
if(py->color==RED)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
pNode->parent->color=BLACK;
py->color=BLACK;
pNode->parent->parent->color=RED;
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if(pNode==pNode->parent->left)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
pNode=pNode->parent;
this->RightRotate(pNode);
}
pNode->parent->color=BLACK;
pNode->parent->parent->color=RED;
this->LeftRotate(pNode->parent->parent);
}
}
}
this->m_pRoot->color=BLACK;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
RBNode
*
RBTree::Max(RBNode
*
pNode)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
while(pNode->left!=nil)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
pNode=pNode->left;
}
return pNode;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
RBNode
*
RBTree::Min(RBNode
*
pNode)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
while(pNode->right!=nil)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
pNode=pNode->right;
}
return pNode;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
RBNode
*
RBTree::Successor(RBNode
*
pNode)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
if(pNode->right!=nil)
return Min(pNode->right);
RBNode* py=pNode->parent;
while(py!=nil&&pNode==py->right)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
pNode=py;
py=py->parent;
}
return py;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
RBNode
*
RBTree::Find(
int
value)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
if(this->m_pRoot==nil)
return NULL;
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
RBNode *pNode=this->m_pRoot;
while(pNode->key!=value&&pNode!=nil)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if(value<pNode->key)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
pNode=pNode->left;
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
pNode=pNode->right;
}
}
return pNode==nil?NULL:pNode;
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
void
RBTree::Delete(
int
value)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
RBNode *pNode=Find(value);
RBNode *py,*px;
if(pNode!=NULL)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if(pNode->left==nil||pNode->right==nil)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
py=pNode;
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
py=this->Successor(pNode);
}
if(py->left!=nil)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
px=py->left;
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
px=py->right;
}
px->parent=py->parent;
if(py->parent==nil)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
m_pRoot=px;
}
else if(py->parent->left=py)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
py->parent->left=px;
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
py->parent->right=px;
}
bool isFix=py->color==BLACK?true:false;
if(py==pNode)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
py->parent=pNode->parent;
py->left=pNode->left;
py->right=pNode->right;
py->color=pNode->color;
delete pNode;
}
if(isFix)
DeleteFixUp(px);
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
void
RBTree::DeleteFixUp(RBNode
*
pNode)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
if(pNode==NULL||pNode==nil)
return;
while(pNode!=this->m_pRoot&&pNode->color==BLACK)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if(pNode==pNode->parent->left)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
RBNode *pw=pNode->parent->right;
//case1:x's sibling w is red
if(pw->color=RED)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
pNode->parent->color=RED;
pw->color=BLACK;
this->LeftRotate(pNode->parent);
pw=pNode->parent->right;
}
//case2:x's sibling w is black, and both of w's children are black
if(pw->left->color==BLACK&&pw->right->color==BLACK)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
pw->color=RED;
pNode=pNode->parent;
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
//case3:x's sibling w is black, w's left child is red, and w's right child is black
if(pw->right->color==BLACK)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
pw->left->color=BLACK;
pw->color=RED;
this->RightRotate(pw);
pw=pNode->parent->right;
}
//case4:x's sibling w is black, and w's right child is red
pw->color=pNode->parent->color;
pNode->parent->color=BLACK;
pw->right->color=BLACK;
this->LeftRotate(pNode->parent);
pNode=this->m_pRoot;
}
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
RBNode *pw=pNode->parent->left;
if(pw->color==RED)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
pNode->parent->color=RED;
pw->color=BLACK;
this->RightRotate(pNode->parent);
pw=pNode->parent->left;
}
if(pw->right->color==BLACK&&pw->left->color==BLACK)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
pw->color=RED;
pNode=pNode->parent;
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if(pw->left->color==BLACK)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
pw->color=RED;
pw->left->color=BLACK;
this->LeftRotate(pw);
pw=pNode->parent->left;
}
pw->color=pNode->parent->color;
pNode->parent->color=BLACK;
pw->left->color=RED;
this->RightRotate(pNode);
pNode=this->m_pRoot;
}
}
}
pNode->color=BLACK;
}