算法导论学习笔记(三)红黑树
红黑树是众多平衡二叉树的一种,顾名思义,它由红黑两种节点构成;
它有以下五点性质:
1. 每个节点或是红色的,或是黑色的;
2. 根节点是黑色的;
3. 每个叶节点(NIL)是黑色的;
4. 如果一个节点是红色的,则其两个子节点都是黑色的;
5. 对于每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点。
当满足以上5个性质的红黑树,就能保证没有一条路径会比其他路径长2倍以上,因而可看作近似平衡。
红黑树是我目前所见过的数据结构中,最为复杂的一种,目前只能初步了解其意图,而不知其真正的原理,故以下代码仍有不足——为经过完整测试,部分代码可能有错。
伪代码
RED-BLACK-INSERT(T, z)
y = T.nil
x = T.root
while x != T.nil
y = x
if z.key < x.key
x = x.left
else x = x.right
z.father = y
if y == T.nil
T.root = z
elseif z.key < y.key
y.left = z
else y.right = z
z.right = T.nil
z.left = T.nil
z.color = RED
RED-BLACK-TREE-INSERT-FIXUP(T, z)
RED-BLACK-TREE-INSERT-FIXUP(T, z)
while z.father.color == RED
if( z.father == ( (z.father).father).left )
y = ( (z.father).father).right
if( y.color == RED)
(z.father).color = BLACK
y.color = BLACK
( (z.father).father).color = RED
z = (z.father).father
else
if z == (z.father).right
z = z.father
LEFT-ROTATE(T,z)
(z.father).color = BLACK
( (z.fater).father).color = RED
RIGHT-ROTATE(T, (z.father).father)
else
y = ( (z.father).father).left
if( y.color == RED)
(z.father).color = BLACK
y.color = BLACK
( (z.father).father).color = RED
z = (z.father).father
else
if z == (z.father).left
z = z.fahter
RIGHT-ROTATE(T, z)
(z.father).color = BLACK
( (z.father).father).color = RED
LEFT-ROTATE(T, (z.father).fater)
LEFT-ROTATE(T, x)
y = x.right
y.father = x.father
if x.father == T.nil
T.root = y
elseif x == (x.father).left
(y.father).left = y
else (y.father).right = y
x.right = y.left
if x.right != T.nill
(x.right).father = x
y.left = x
x.father = y
RIGHT-ROTATE(T, x)
y = x.left
y.father = x.father
if x.father == T.nil
T.root = y
elseif x == (x.father).right
(x.father).right = y
else (x.father).left = y
x.left = y.right
if x.left != T.nil
(x.left).father = x
y.right = x
x.father = y
RED-BLACK-DELETE( T, z )
y = z
y-original-color = y.color
if z.left == T.nil
x = z.right
RED-BLACK-TRANSPLANT( T, z, z.right )
elseif z.right == T.nil
x = z.left
RED-BLACK-TRANSPLANT( T, z, z.left )
else
y = getNextTreePoint( z.right )
y-original-color = y.color
x = y.right
if y.p == z
x.p = y
else
RED-BLACK-TRANSPLANT( T, y, y.right )
y.right = z.right
y.right.p = y
RED-BLACK-TRANSPLANT( T, z, y )
y.left = z.left
y.left.p = y
y.color = z.color
if y-original-color == BLACK
RED-BLACK-DELETE-FIXUP( T, x )
RED-BLACK-TRANSPLANT( T, u, v )
if u.p == T.nil
T.root = v
elseif u == u.p.left
u.p.left = v
else
u.p.right = v
v.p = u.p
RED-BLACK-DELETE-FIXUP( T, x )
while x != T.root and x.color == BLACK
if x == x.p.left
w = x.p.right
if w.color == RED
w.color = BLACK
x.p.color = RED
LEFT-ROATE( T, x.p )
w = x.p.right
if w.left.color == BLACK and w.right.color == BLACK
w.color = RED
x = x.p
else
if w.right.color == BLACK
w.left.color = BLACK
w.color = RED
RIGHT-ROATE( T, w )
w = x.p.right
w.color = x.p.color
x.p.color = BLACK
w.right.color = BLACK
LEFT-ROATE( T, x.p )
x = T.root
else
w = x.p.left
if w.color == RED
w.color = BLACK
x.p.color = RED
RIGHT-ROATE( T, x.p )
w = x.p.left
if w.right.color == BLACK and w.left.color == BLACK
w.color = RED
x = x.p
else
if w.left.color == BLACK
w.right.color = BLACK
w.color = RED
LEFT-ROATE( T, w)
w = x.p.left
w.color = x.p.color
x.p.color = BLACK
w.left.color = BLACK
RIGHT-ROATE( T, x.p )
x = T.root
x.color = BLACK
代码实现
#include <iostream>
#define RED true
#define BLACK false
using namespace std;
struct TreePoint
{
int key;
bool color;
TreePoint* father;
TreePoint* right;
TreePoint* left;
TreePoint(){}
TreePoint(int key) {
this->key = key;
father = NULL;
right = NULL;
left = NULL;
}
};
struct RedBlackTree
{
TreePoint* root;
TreePoint* nil;
RedBlackTree(){
nil = new TreePoint();
nil->color = BLACK;
root = nil;
root->father = nil;
}
};
void leftRotate(RedBlackTree &, TreePoint* );
void rightRotate(RedBlackTree &, TreePoint* );
TreePoint* getNextTreePoint(RedBlackTree &, TreePoint*);
void transplantRedBlackTree(RedBlackTree &, TreePoint* ,TreePoint* );
void fixUpRedBlackTreeInserting(RedBlackTree &, TreePoint*);
void insertRedBlackTree(RedBlackTree &, TreePoint* );
void fixUpRedBlackTreeDeleting(RedBlackTree &, TreePoint*);
void deleteRedBlackTree(RedBlackTree &, TreePoint* );
TreePoint* findPoint(RedBlackTree &,TreePoint* , int );
void show(RedBlackTree &, TreePoint* );
int main()
{
RedBlackTree redBlackTree;
int n = 10;
cin>>n;
//while(n--) {
int key;
for(int i=0;i<n;++i){
cin>>key;
insertRedBlackTree(redBlackTree,new TreePoint(key));
}
show(redBlackTree,redBlackTree.root);
cout<<endl;
key = 7;
TreePoint* find = findPoint(redBlackTree,redBlackTree.root,key);
deleteRedBlackTree(redBlackTree,find);
show(redBlackTree,redBlackTree.root);
cout<<endl;
}
void insertRedBlackTree(RedBlackTree &T,TreePoint* z){
TreePoint* y = T.nil;
TreePoint* x = T.root;
while( x != T.nil ) {
y = x;
if(z->key < x->key) {
x = x->left;
}
else {
x = x->right;
}
}
z->father = y;
if (y == T.nil) {
T.root = z;
}
else if(z->key < y->key) {
y->left = z;
}
else {
y->right = z;
}
z->right = T.nil;
z->left = T.nil;
z->color = RED;
fixUpRedBlackTreeInserting(T,z);
}
void fixUpRedBlackTreeInserting(RedBlackTree &T,TreePoint* z) {
while( (z->father)->color == RED) {
TreePoint* y;
if( z->father == ( (z->father)->father)->left) {
y = ( (z->father)->father)->right;
if( y->color == RED) {
(z->father)->color = BLACK;
y->color = BLACK;
( (z->father)->father)->color = RED;
z = (z->father)->father;
}
else {
if( z == (z->father)->right) {
z = z->father;
leftRotate(T,z);
}
(z->father)->color = BLACK;
( (z->father)->father)->color = RED;
rightRotate(T,(z->father)->father);
}
}
else {
y = ( (z->father)->father)->left;
if( y->color == RED) {
(z->father)->color = BLACK;
y->color = BLACK;
( (z->father)->father)->color = RED;
z = (z->father)->father;
}
else {
if( z == (z->father)->left) {
z = z->father;
rightRotate(T,z);
}
(z->father)->color = BLACK;
( (z->father)->father)->color = RED;
leftRotate(T,(z->father)->father);
}
}
}
(T.root)->color = BLACK;
}
void deleteRedBlackTree(RedBlackTree &T, TreePoint* z) {
TreePoint* y = z;
TreePoint* x;
bool originalColor_y = y->color;
if( z->left == T.nil ) {
x = z->right;
transplantRedBlackTree(T,z,z->right);
}
else if( z->right == T.nil) {
x = z->left;
transplantRedBlackTree(T,z,z->left);
}
else {
y = getNextTreePoint(T,z->right);
originalColor_y = y->color;
x = y->right;
if( y->father == z) {
x->father = y;
}
else {
transplantRedBlackTree(T,y,y->right);
y->right = z->right;
(y->right)->father = y;
}
transplantRedBlackTree(T,z,y);
y->left = z->left;
(y->left)->father = y;
y->color = z->color;
}
if( originalColor_y == BLACK) {
fixUpRedBlackTreeDeleting(T,x);
}
}
void fixUpRedBlackTreeDeleting(RedBlackTree &T, TreePoint* x) {
while( x != T.root && x->color == BLACK) {
TreePoint* w;
if( x== (x->father)->left) {
w = (x->father)->right;
if( w->color == RED) {
w->color = BLACK;
(x->father)->color = RED;
leftRotate(T,x->father);
w = (x->father)->right;
}
if( (w->left)->color == BLACK && (w->right)->color == BLACK) {
w->color = RED;
x = x->father;
}
else {
if( (w->right)->color == BLACK) {
(w->left)->color = BLACK;
w->color = RED;
rightRotate(T,w);
w = (x->father)->right;
}
w->color = (x->father)->color;
(x->father)->color = BLACK;
(w->right)->color = BLACK;
leftRotate(T,x->father);
x = T.root;
}
}
else {
w = (x->father)->left;
if( w->color == RED) {
w->color = BLACK;
(x->father)->color = RED;
rightRotate(T,x->father);
w = (x->father)->left;
}
if( (w->right)->color == BLACK && (w->left)->color == BLACK) {
w->color = RED;
x = x->father;
}
else {
if( (w->left)->color == BLACK) {
(w->right)->color = BLACK;
w->color = RED;
leftRotate(T,w);
w = (x->father)->left;
}
w->color = (x->father)->color;
(x->father)->color = BLACK;
(w->left)->color = BLACK;
rightRotate(T,x->father);
x = T.root;
}
}
}
x->color = BLACK;
}
void leftRotate(RedBlackTree &T,TreePoint* x) {
TreePoint* y;
y = x->right;
y->father = x->father;
if( x->father == T.nil) {
T.root = y;
}
else if( x == (x->father)->left) {
(y->father)->left = y;
}
else {
(y->father)->right = y;
}
x->right = y->left;
if( x->right != T.nil ) {
(x->right)->father = x;
}
y->left = x;
x->father = y;
}
void rightRotate(RedBlackTree &T,TreePoint* x) {
TreePoint* y;
y = x->left;
y->father = x->father;
if( x->father == T.nil) {
T.root = y;
}
else if( x == (x->father)->right) {
(y->father)->right = y;
}
else {
(y->father)->left = y;
}
x->left = y->right;
if( x->left != T.nil ) {
(x->left)->father = x;
}
y->right = x;
x->father = y;
}
void transplantRedBlackTree(RedBlackTree &T, TreePoint* u,TreePoint* v) {
if( u->father == T.nil ) {
T.root = v;
}
else if( u == (u->father)->left ) {
(u->father)->left = v;
}
else {
(u->father)->right = v;
}
v->father = u->father;
}
TreePoint* getNextTreePoint(RedBlackTree &T, TreePoint* x) {
while(x->left != T.nil){
x = x->left;
}
return x;
}
TreePoint* findPoint(RedBlackTree &T, TreePoint* p, int key) {
if(p == T.nil){
return NULL;
}
else if(p->key == key){
return p;
}
else if(p->key > key ) {
return findPoint(T,p->left,key);
}
else {
return findPoint(T,p->right,key);
}
}
void show(RedBlackTree &T,TreePoint* p) {
cout<<p->key<<" ";
if( p->left != T.nil ) {
show(T,p->left);
}
//cout<<p->key<<" ";
if( p->right != T.nil ) {
show(T,p->right);
}
//cout<<p->key<<" ";
}
/*
9
11 2 14 1 15 7 5 8 4
*/