编程练习——红黑树(RedBlackTree)
2008-09-09 16:48
453 查看
在网上搜索了很多红黑树的资源,发现自己看代码的能力还是有些欠缺。很多都看不懂,后来找到一篇英文红黑树文献,终于弄明白了红黑树的删除插入是怎么做的。但是那片文献好像还有些漏洞,其中有一种删除情况,他并没有考虑到。如果大家想看的话可以搜索下 "red-black trees" ,由 prof. Lyn Turbak所写。因为时间关系,插入算法只是实现了非CLR算法。删除算法我也不知道叫什么名字(文献里没有讲)。但是删除结果依旧符合红黑树。
建立红黑树节点的时候,考虑到因为经常要和一个节点的父亲节点打交道,所以采用了在节点里添加父亲节点的指针的方法。这样即方便也提高效率。另外也好调试。如果一味采用递归..估计人会看疯掉的。插入的时候,采用的是先插入删除的时候红色节点,然后在判断是否违反红红条件。违反的话就左旋右旋进行调整。否则就插入成功。删除的时候先删除节点,这个过程和删除二叉查找树节点一致。删除时要看真正要删除的节点是否是根节点,是否是黑色节点。因为红色节点和根节点删除不会调整树形。如果删除的是黑色节点,那么要看替换他的节点(这里的替换一定是左子树树根,因为如果有右子树,那么被删除的也不会是这个节点,记住二叉查找树的删除过程)是否是黑色节点(这里如果左子树为空,那他也是黑色节点)。如果是黑色节点,那么一定要调整树的结构,否则就直接染色。调整树结构时要考虑的情况就非常多了。一共有9种情况需要考虑。
下面是代码部分,删除时如何调整在代码注释中。至于insert操作,看看文献就应该会做了。
/*
* create RBNode class for construction RBTree
* create by chico chen
* date: 2008/09/04
* 如需转载注明出处
*/
template<class T>
#define RED 0
#define BLACK 1
class RBNode
{
public:
T data;
RBNode<T>* left;
RBNode<T>* right;
RBNode<T>* parent;
int color;
RBNode(T& data)
{
this->data = data;
left = NULL;
right = NULL;
parent = NULL;
color = RED;
}
RBNode(T& data, RBNode<T>* left, RBNode<T>* right, RBNode<T>* parent)
{
this->data = data;
this->left = left;
this->right = right;
this->parent = parent;
color = RED;
}
~RBNode()
{
this->left = this->right = this->parent = NULL;
color = RED;
}
};
下面是红黑树代码
/*
* this is red-black-tree code
* this code is not efficent in inserting
*
* create by chico chen
* date: 2008/09/04
* 如需转载注明出处
*/
#include "RBNode.h"
template<class T>
class RBTree
{
private:
RBNode<T>* root;
public:
RBTree()
{
this->root = NULL;
}
~RBTree()
{
clearTree(this->root);
}
void print()
{
print(this->root,0);
}
void insert(T& data)
{
RBNode<T>* node = new RBNode<T>(data);
insertNode(node);
}
void deleteKey(T& data)
{
deleteNode(data);
}
bool RBTreeTest()
{
try
{
getBlackNum(this->root);
}
catch(...)
{
return false;
}
return true;
}
private:
void print(RBNode<T>* subRoot, int num)
{
if(subRoot != NULL)
{
print(subRoot->right,num+3);
for(int i = 0; i < num; i++)
{
cout << " ";
}
cout << subRoot->data<<"("<<subRoot->color<<")"<<endl;
print(subRoot->left,num+3);
}
}
void clearTree(RBNode<T>* subRoot)
{
if(subRoot == NULL)
return;
clearTree(subRoot->left);
clearTree(subRoot->right);
delete subRoot;
}
RBNode<T>* deleteMin(RBNode<T>* subRoot,RBNode<T>** parent)
{
while(subRoot != NULL)
{
parent = &subRoot;
if(subRoot->right != NULL)
{
subRoot = subRoot->right;
}
else
{
break;
}
}
return subRoot;
}
void deleteNode(T& data)
{
if(root == NULL)
{
throw "Empty tree";
}
RBNode<T>* subRoot = root;
while(subRoot != NULL)
{
if(subRoot->data > data)
{
subRoot = subRoot->left;
}
else if(subRoot->data < data)
{
subRoot = subRoot->right;
}
else
{
// find the data
// use the midOrder last one which is before the data node to replace
RBNode<T>* inParent = subRoot;
RBNode<T>* deleteNode = deleteMin(subRoot->left,&inParent);
RBNode<T>* realDelete = NULL;
if(deleteNode != NULL)
{
subRoot->data = deleteNode->data; // copy
realDelete = deleteNode;
//real delete
}
else
{
realDelete = subRoot;
//real delete
}
if(realDelete->parent == NULL)
{
// delete root
delete realDelete;
}
else
{
// nothing at realDelete->right
RBNode<T>* parent = realDelete->parent;
RBNode<T>* subATree = NULL;
if(parent->left == realDelete)
{
parent->left = realDelete->left;
}
else
{
parent->right = realDelete->left;
}
subATree = realDelete->left;
if(realDelete->left != NULL)
{
realDelete->left->parent = parent;
}
int color = realDelete->color;
delete realDelete;
if(color == BLACK &&
(subATree == NULL || subATree->color == BLACK))
{
deleteRebuild(subATree,parent);
}
else if(color == BLACK && subATree->color == RED)
{
subATree->color = BLACK;
}
else
{
// do nothing
}
break;
}
}
}
}
/* delete them if you want
*
// x(r) c(r)
// / / / /
// `a(b) b(b) --> x(b) b(b)
// / /
// c(r) a(b)
// LRL means L-> double black is at left, and rotate is RL
RBNode<T>* LRLCaseA(RBNode<T>* x)
{
RLRotate(x,x->right,x->right->left);
x->color = BLACK;
return x->parent;
}
// x(r) b(r)
// / / / /
// `a(b) b(b) --> x(b) c(b)
// / /
// c(r) a(b)
RBNode<T>* LLLCaseA(RBNode<T>* x)
{
RRRotate(x,x->right);
x->color = BLACK;
x->parent->color = RED;
x->parent->right->color = BLACK;
return x->parent;
}
// x(r) b(r)
// / / / /
// b(b) `a(b)--> c(b) x(b)
// / /
// c(r) a(b)
RBNode<T>* RLLCaseA(RBNode<T>* x)
{
LLRotate(x,x->left);
x->color = BLACK;
x->parent->color = RED;
x->parent->left->color = BLACK;
return x->parent;
}
// x(r) c(r)
// / / / /
// b(b) `a(b)--> b(b) x(b)
// / /
// c(r) a(b)
RBNode<T>* RLRCaseA(RBNode<T>* x)
{
LRRotate(x,x->left,x->left->right);
x->color = BLACK;
return x->parent;
}
// x(r) x(b)
// / / / /
// `a(b) c(b) -> a(b) c(r)
// / / / /
// d(b) e(b) d(b) e(b)
RBNode<T>* LCaseB(RBNode<T>* x)
{
x->color = BLACK;
x->right->color = RED;
}
// x(r) x(b)
// / / / /
// c(b) `a(b) -> c(r) a(b)
// / / / /
// d(b) e(b) d(b) e(b)
RBNode<T>* RCaseB(RBNode<T>* x)
{
x->color = BLACK;
x->left->color = RED;
}
// x(b) c(b)
// / / / /
// `a(b) c(r) -> x(r) e(b)
// / / / /
// d(b) e(b) `a(b) d(b)
RBNode<T>* LCaseC(RBNode<T>* x)
{
RRRotate(x,x->right);
x->color = RED;
x->parent->color = BLACK;
return x->parent;
}
// x(b) c(b)
// / / / /
// c(r) `a(b) -> d(b) x(r)
// / / / /
// d(b) e(b) e(b) `a(b)
RBNode<T>* RCaseC(RBNode<T>* x)
{
LLRotate(x,x->left);
x->color = RED;
x->parent->color = BLACK;
return x->parent;
}
*
*/
bool isBlack(RBNode<T>* node)
{
if(node == NULL || node->color == BLACK)
return true;
return false;
}
void rebuild(RBNode<T>* node)
{
if(node->parent->data > node->data)
{
node->parent->left = node;
}
else
{
node->parent->right = node;
}
}
/*
* There are 9 cases we will meet. The cases of the double black node at the right is ignored.
* (b) means black node, (db) means double black node, (r) means red node
* 1. (b) 2 (b) 3 (b)
* / / / / / /
* (db) (b) (db) (b) (db) (b)
* / / / / / /
* (b) (b) (r) (b) (b) (r)
*
* 4. (b) 5 (b) 6 (r)
* / / / / / /
* (db) (b) (db) (r) (db) (b)
* / / / / / /
* (r) (r) (b) (b) (b) (b)
*
* 7. (r) 8 (r) 9 (r)
* / / / / / /
* (db) (b) (db) (b) (db) (b)
* / / / / / /
* (r) (b) (b) (r) (r) (r)
*
* case 1,6: up the black, if the parent is black then call the function again until the
* double black node is root, else blacken the parent.
* case 2,4,7,9: call the RLRotate, if the parent of the double
* node is black, up the black and call the function again, else
* blacken the parent.
* case 3,8: call the LLRotate, the same as case 2.
* case 5: call LLRotate, change as (b) then end.
* / /
* (b) (b)
* / /
* (b) (r)
*
*/
void deleteRebuild(RBNode<T>* node,RBNode<T>* parent)
{
if(parent == NULL)
{
// root, delete the black
return;
}
if(parent->left == node)
{
RBNode<T>* brother = parent->right;
RBNode<T>* nephewA = brother->left;
RBNode<T>* nephewB = brother->right;
if(isBlack(nephewA) && isBlack(nephewB) && isBlack(brother))
{
// case 1,6
brother->color = RED;
if(parent->color == BLACK)
{
deleteRebuild(parent,parent->parent);
}
else
{
parent->color = BLACK;
return;
}
}
else if(!isBlack(nephewA))
{
// case 2,4,7,9
RBNode<T>* tempRoot = RLRotate(parent,brother,nephewA);
// rebuild
rebuild(tempRoot);
}
else if(!isBlack(nephewB))
{
// case 3,8
RBNode<T>* tempRoot = RRRotate(parent,brother);
rebuild(tempRoot);
nephewB->color = BLACK;
brother->color = RED;
}
else if(!isBlack(brother))
{
// case 5
RBNode<T>* tempRoot = RRRotate(parent,brother);
rebuild(tempRoot);
brother->color = BLACK;
nephewA->color = RED;
return;
}
else
{
// unknown
throw "none excption, about there is no red or black";
}
if(parent->color == BLACK)
{
// case 2,3,4
deleteRebuild(parent,parent->parent);
}
else
{
// case 7,8,9
parent->color = BLACK;
}
}
else
{
RBNode<T>* brother = parent->left;
RBNode<T>* nephewA = brother->right;
RBNode<T>* nephewB = brother->left;
if(isBlack(nephewA) && isBlack(nephewB) && isBlack(brother))
{
brother->color = RED;
if(parent->color == BLACK)
{
deleteRebuild(parent,parent->parent);
}
else
{
parent->color = BLACK;
return;
}
}
else if(!isBlack(nephewA))
{
RBNode<T>* tempRoot = LRRotate(parent,brother,nephewA);
// rebuild
rebuild(tempRoot);
}
else if(!isBlack(nephewB))
{
RBNode<T>* tempRoot = LLRotate(parent,brother);
rebuild(tempRoot);
nephewB->color = BLACK;
brother->color = RED;
}
else if(!isBlack(brother))
{
RBNode<T>* tempRoot = LLRotate(parent,brother);
rebuild(tempRoot);
nephewA->color = RED;
brother->color = BLACK;
return;
}
else
{
throw "none excption, about there is no red or black";
}
if(parent->color == BLACK)
{
deleteRebuild(parent,parent->parent);
}
else
{
parent->color = BLACK;
}
}
}
void insertNode(RBNode<T>* node)
{
if(root == NULL)
{
root = node;
node->color = BLACK;
return;
}
RBNode<T>* subRoot = root;
RBNode<T>* insertPoint = NULL;
while(subRoot!=NULL)
{
insertPoint = subRoot;
if(subRoot->data > node->data)
{
// insert left
subRoot = subRoot->left;
}
else if(subRoot->data < node->data)
{
subRoot = subRoot->right;
}
else
{
throw "same key";
}
}
if(insertPoint->data > node->data)
{
insertPoint->left = node;
}
else
{
insertPoint->right = node;
}
node->parent = insertPoint;
insertRebuild(node);
}
// return the subRoot
// a b
// / / /
// b -> c a
// /
// c
RBNode<T>* LLRotate(RBNode<T>* a, RBNode<T>* b)
{
if(b->right != NULL)
{
b->right->parent = a;
}
a->left = b->right;
b->right = a;
b->parent = a->parent;
a->parent = b;
return b;
}
// return the subRoot
// a b
// / / /
// b -> a c
// /
// c
RBNode<T>* RRRotate(RBNode<T>* a, RBNode<T>* b)
{
if(b->left != NULL)
{
b->left->parent = a;
}
a->right = b->left;
b->left = a;
b->parent = a->parent;
a->parent = b;
return b;
}
// return the subRoot
// a c
// / / /
// b -> a b
// / /
// c d
// /
// d
RBNode<T>* RLRotate(RBNode<T>* a, RBNode<T>* b, RBNode<T>* c)
{
if(c->right != NULL)
{
c->right->parent = b;
}
b->left = c->right;
c->right = b;
b->parent = c;
if(c->left != NULL)
{
c->left->parent = a;
}
a->right = c->left;
c->left = a;
c->parent = a->parent;
a->parent = c;
return c;
}
// return the subRoot
// a c
// / / /
// b -> b a
// / /
// c d
// /
// d
RBNode<T>* LRRotate(RBNode<T>* a, RBNode<T>* b, RBNode<T>* c)
{
if(c->left != NULL)
{
c->left->parent = b;
}
b->right = c->left;
c->left = b;
b->parent = c;
if(c->right!= NULL)
{
c->right->parent = a;
}
a->left = c->right;
c->right = a;
c->parent = a->parent;
a->parent = c;
return c;
}
// node is not the root
void insertRebuild(RBNode<T>* node)
{
RBNode<T>* parent = NULL;
RBNode<T>* grandParent = NULL;
while(node->parent != NULL)
{
parent = node->parent;
if(parent->color == RED)// here means there must be a grandparent
{
grandParent = parent->parent;
grandParent->color = BLACK;
if(grandParent->left == parent)
{
if(parent->left == node)
{
//LLRotate
node->color = BLACK;
node = LLRotate(grandParent,parent);
}
else
{
//LRRotate
parent->color = BLACK;
node = LRRotate(grandParent,parent,node);
}
}
else
{
if(parent->left == node)
{
//RLRotate
parent->color = BLACK;
node = RLRotate(grandParent,parent,node);
}
else
{
//RRRotate
node->color = BLACK;
node = RRRotate(grandParent,parent);
}
}
}
else
{
break;
}
}
if(node->parent == NULL)
{
node->color = BLACK;
this->root = node;
}
else
{
rebuild(node);
/*if(node->parent->data > node->data)
{
node->parent->left = node;
}
else
{
node->parent->right = node;
}*/
}
}
int getBlackNum(RBNode<T>* subRoot)
{
if(subRoot == NULL)
{
return 1;
}
int left = getBlackNum(subRoot->left);
int right = getBlackNum(subRoot->right);
if(left != right)
{
throw "wrong";
}
if(subRoot->color == BLACK)
{
return 1+left;
}
else
{
return left;
}
}
};
建立红黑树节点的时候,考虑到因为经常要和一个节点的父亲节点打交道,所以采用了在节点里添加父亲节点的指针的方法。这样即方便也提高效率。另外也好调试。如果一味采用递归..估计人会看疯掉的。插入的时候,采用的是先插入删除的时候红色节点,然后在判断是否违反红红条件。违反的话就左旋右旋进行调整。否则就插入成功。删除的时候先删除节点,这个过程和删除二叉查找树节点一致。删除时要看真正要删除的节点是否是根节点,是否是黑色节点。因为红色节点和根节点删除不会调整树形。如果删除的是黑色节点,那么要看替换他的节点(这里的替换一定是左子树树根,因为如果有右子树,那么被删除的也不会是这个节点,记住二叉查找树的删除过程)是否是黑色节点(这里如果左子树为空,那他也是黑色节点)。如果是黑色节点,那么一定要调整树的结构,否则就直接染色。调整树结构时要考虑的情况就非常多了。一共有9种情况需要考虑。
下面是代码部分,删除时如何调整在代码注释中。至于insert操作,看看文献就应该会做了。
/*
* create RBNode class for construction RBTree
* create by chico chen
* date: 2008/09/04
* 如需转载注明出处
*/
template<class T>
#define RED 0
#define BLACK 1
class RBNode
{
public:
T data;
RBNode<T>* left;
RBNode<T>* right;
RBNode<T>* parent;
int color;
RBNode(T& data)
{
this->data = data;
left = NULL;
right = NULL;
parent = NULL;
color = RED;
}
RBNode(T& data, RBNode<T>* left, RBNode<T>* right, RBNode<T>* parent)
{
this->data = data;
this->left = left;
this->right = right;
this->parent = parent;
color = RED;
}
~RBNode()
{
this->left = this->right = this->parent = NULL;
color = RED;
}
};
下面是红黑树代码
/*
* this is red-black-tree code
* this code is not efficent in inserting
*
* create by chico chen
* date: 2008/09/04
* 如需转载注明出处
*/
#include "RBNode.h"
template<class T>
class RBTree
{
private:
RBNode<T>* root;
public:
RBTree()
{
this->root = NULL;
}
~RBTree()
{
clearTree(this->root);
}
void print()
{
print(this->root,0);
}
void insert(T& data)
{
RBNode<T>* node = new RBNode<T>(data);
insertNode(node);
}
void deleteKey(T& data)
{
deleteNode(data);
}
bool RBTreeTest()
{
try
{
getBlackNum(this->root);
}
catch(...)
{
return false;
}
return true;
}
private:
void print(RBNode<T>* subRoot, int num)
{
if(subRoot != NULL)
{
print(subRoot->right,num+3);
for(int i = 0; i < num; i++)
{
cout << " ";
}
cout << subRoot->data<<"("<<subRoot->color<<")"<<endl;
print(subRoot->left,num+3);
}
}
void clearTree(RBNode<T>* subRoot)
{
if(subRoot == NULL)
return;
clearTree(subRoot->left);
clearTree(subRoot->right);
delete subRoot;
}
RBNode<T>* deleteMin(RBNode<T>* subRoot,RBNode<T>** parent)
{
while(subRoot != NULL)
{
parent = &subRoot;
if(subRoot->right != NULL)
{
subRoot = subRoot->right;
}
else
{
break;
}
}
return subRoot;
}
void deleteNode(T& data)
{
if(root == NULL)
{
throw "Empty tree";
}
RBNode<T>* subRoot = root;
while(subRoot != NULL)
{
if(subRoot->data > data)
{
subRoot = subRoot->left;
}
else if(subRoot->data < data)
{
subRoot = subRoot->right;
}
else
{
// find the data
// use the midOrder last one which is before the data node to replace
RBNode<T>* inParent = subRoot;
RBNode<T>* deleteNode = deleteMin(subRoot->left,&inParent);
RBNode<T>* realDelete = NULL;
if(deleteNode != NULL)
{
subRoot->data = deleteNode->data; // copy
realDelete = deleteNode;
//real delete
}
else
{
realDelete = subRoot;
//real delete
}
if(realDelete->parent == NULL)
{
// delete root
delete realDelete;
}
else
{
// nothing at realDelete->right
RBNode<T>* parent = realDelete->parent;
RBNode<T>* subATree = NULL;
if(parent->left == realDelete)
{
parent->left = realDelete->left;
}
else
{
parent->right = realDelete->left;
}
subATree = realDelete->left;
if(realDelete->left != NULL)
{
realDelete->left->parent = parent;
}
int color = realDelete->color;
delete realDelete;
if(color == BLACK &&
(subATree == NULL || subATree->color == BLACK))
{
deleteRebuild(subATree,parent);
}
else if(color == BLACK && subATree->color == RED)
{
subATree->color = BLACK;
}
else
{
// do nothing
}
break;
}
}
}
}
/* delete them if you want
*
// x(r) c(r)
// / / / /
// `a(b) b(b) --> x(b) b(b)
// / /
// c(r) a(b)
// LRL means L-> double black is at left, and rotate is RL
RBNode<T>* LRLCaseA(RBNode<T>* x)
{
RLRotate(x,x->right,x->right->left);
x->color = BLACK;
return x->parent;
}
// x(r) b(r)
// / / / /
// `a(b) b(b) --> x(b) c(b)
// / /
// c(r) a(b)
RBNode<T>* LLLCaseA(RBNode<T>* x)
{
RRRotate(x,x->right);
x->color = BLACK;
x->parent->color = RED;
x->parent->right->color = BLACK;
return x->parent;
}
// x(r) b(r)
// / / / /
// b(b) `a(b)--> c(b) x(b)
// / /
// c(r) a(b)
RBNode<T>* RLLCaseA(RBNode<T>* x)
{
LLRotate(x,x->left);
x->color = BLACK;
x->parent->color = RED;
x->parent->left->color = BLACK;
return x->parent;
}
// x(r) c(r)
// / / / /
// b(b) `a(b)--> b(b) x(b)
// / /
// c(r) a(b)
RBNode<T>* RLRCaseA(RBNode<T>* x)
{
LRRotate(x,x->left,x->left->right);
x->color = BLACK;
return x->parent;
}
// x(r) x(b)
// / / / /
// `a(b) c(b) -> a(b) c(r)
// / / / /
// d(b) e(b) d(b) e(b)
RBNode<T>* LCaseB(RBNode<T>* x)
{
x->color = BLACK;
x->right->color = RED;
}
// x(r) x(b)
// / / / /
// c(b) `a(b) -> c(r) a(b)
// / / / /
// d(b) e(b) d(b) e(b)
RBNode<T>* RCaseB(RBNode<T>* x)
{
x->color = BLACK;
x->left->color = RED;
}
// x(b) c(b)
// / / / /
// `a(b) c(r) -> x(r) e(b)
// / / / /
// d(b) e(b) `a(b) d(b)
RBNode<T>* LCaseC(RBNode<T>* x)
{
RRRotate(x,x->right);
x->color = RED;
x->parent->color = BLACK;
return x->parent;
}
// x(b) c(b)
// / / / /
// c(r) `a(b) -> d(b) x(r)
// / / / /
// d(b) e(b) e(b) `a(b)
RBNode<T>* RCaseC(RBNode<T>* x)
{
LLRotate(x,x->left);
x->color = RED;
x->parent->color = BLACK;
return x->parent;
}
*
*/
bool isBlack(RBNode<T>* node)
{
if(node == NULL || node->color == BLACK)
return true;
return false;
}
void rebuild(RBNode<T>* node)
{
if(node->parent->data > node->data)
{
node->parent->left = node;
}
else
{
node->parent->right = node;
}
}
/*
* There are 9 cases we will meet. The cases of the double black node at the right is ignored.
* (b) means black node, (db) means double black node, (r) means red node
* 1. (b) 2 (b) 3 (b)
* / / / / / /
* (db) (b) (db) (b) (db) (b)
* / / / / / /
* (b) (b) (r) (b) (b) (r)
*
* 4. (b) 5 (b) 6 (r)
* / / / / / /
* (db) (b) (db) (r) (db) (b)
* / / / / / /
* (r) (r) (b) (b) (b) (b)
*
* 7. (r) 8 (r) 9 (r)
* / / / / / /
* (db) (b) (db) (b) (db) (b)
* / / / / / /
* (r) (b) (b) (r) (r) (r)
*
* case 1,6: up the black, if the parent is black then call the function again until the
* double black node is root, else blacken the parent.
* case 2,4,7,9: call the RLRotate, if the parent of the double
* node is black, up the black and call the function again, else
* blacken the parent.
* case 3,8: call the LLRotate, the same as case 2.
* case 5: call LLRotate, change as (b) then end.
* / /
* (b) (b)
* / /
* (b) (r)
*
*/
void deleteRebuild(RBNode<T>* node,RBNode<T>* parent)
{
if(parent == NULL)
{
// root, delete the black
return;
}
if(parent->left == node)
{
RBNode<T>* brother = parent->right;
RBNode<T>* nephewA = brother->left;
RBNode<T>* nephewB = brother->right;
if(isBlack(nephewA) && isBlack(nephewB) && isBlack(brother))
{
// case 1,6
brother->color = RED;
if(parent->color == BLACK)
{
deleteRebuild(parent,parent->parent);
}
else
{
parent->color = BLACK;
return;
}
}
else if(!isBlack(nephewA))
{
// case 2,4,7,9
RBNode<T>* tempRoot = RLRotate(parent,brother,nephewA);
// rebuild
rebuild(tempRoot);
}
else if(!isBlack(nephewB))
{
// case 3,8
RBNode<T>* tempRoot = RRRotate(parent,brother);
rebuild(tempRoot);
nephewB->color = BLACK;
brother->color = RED;
}
else if(!isBlack(brother))
{
// case 5
RBNode<T>* tempRoot = RRRotate(parent,brother);
rebuild(tempRoot);
brother->color = BLACK;
nephewA->color = RED;
return;
}
else
{
// unknown
throw "none excption, about there is no red or black";
}
if(parent->color == BLACK)
{
// case 2,3,4
deleteRebuild(parent,parent->parent);
}
else
{
// case 7,8,9
parent->color = BLACK;
}
}
else
{
RBNode<T>* brother = parent->left;
RBNode<T>* nephewA = brother->right;
RBNode<T>* nephewB = brother->left;
if(isBlack(nephewA) && isBlack(nephewB) && isBlack(brother))
{
brother->color = RED;
if(parent->color == BLACK)
{
deleteRebuild(parent,parent->parent);
}
else
{
parent->color = BLACK;
return;
}
}
else if(!isBlack(nephewA))
{
RBNode<T>* tempRoot = LRRotate(parent,brother,nephewA);
// rebuild
rebuild(tempRoot);
}
else if(!isBlack(nephewB))
{
RBNode<T>* tempRoot = LLRotate(parent,brother);
rebuild(tempRoot);
nephewB->color = BLACK;
brother->color = RED;
}
else if(!isBlack(brother))
{
RBNode<T>* tempRoot = LLRotate(parent,brother);
rebuild(tempRoot);
nephewA->color = RED;
brother->color = BLACK;
return;
}
else
{
throw "none excption, about there is no red or black";
}
if(parent->color == BLACK)
{
deleteRebuild(parent,parent->parent);
}
else
{
parent->color = BLACK;
}
}
}
void insertNode(RBNode<T>* node)
{
if(root == NULL)
{
root = node;
node->color = BLACK;
return;
}
RBNode<T>* subRoot = root;
RBNode<T>* insertPoint = NULL;
while(subRoot!=NULL)
{
insertPoint = subRoot;
if(subRoot->data > node->data)
{
// insert left
subRoot = subRoot->left;
}
else if(subRoot->data < node->data)
{
subRoot = subRoot->right;
}
else
{
throw "same key";
}
}
if(insertPoint->data > node->data)
{
insertPoint->left = node;
}
else
{
insertPoint->right = node;
}
node->parent = insertPoint;
insertRebuild(node);
}
// return the subRoot
// a b
// / / /
// b -> c a
// /
// c
RBNode<T>* LLRotate(RBNode<T>* a, RBNode<T>* b)
{
if(b->right != NULL)
{
b->right->parent = a;
}
a->left = b->right;
b->right = a;
b->parent = a->parent;
a->parent = b;
return b;
}
// return the subRoot
// a b
// / / /
// b -> a c
// /
// c
RBNode<T>* RRRotate(RBNode<T>* a, RBNode<T>* b)
{
if(b->left != NULL)
{
b->left->parent = a;
}
a->right = b->left;
b->left = a;
b->parent = a->parent;
a->parent = b;
return b;
}
// return the subRoot
// a c
// / / /
// b -> a b
// / /
// c d
// /
// d
RBNode<T>* RLRotate(RBNode<T>* a, RBNode<T>* b, RBNode<T>* c)
{
if(c->right != NULL)
{
c->right->parent = b;
}
b->left = c->right;
c->right = b;
b->parent = c;
if(c->left != NULL)
{
c->left->parent = a;
}
a->right = c->left;
c->left = a;
c->parent = a->parent;
a->parent = c;
return c;
}
// return the subRoot
// a c
// / / /
// b -> b a
// / /
// c d
// /
// d
RBNode<T>* LRRotate(RBNode<T>* a, RBNode<T>* b, RBNode<T>* c)
{
if(c->left != NULL)
{
c->left->parent = b;
}
b->right = c->left;
c->left = b;
b->parent = c;
if(c->right!= NULL)
{
c->right->parent = a;
}
a->left = c->right;
c->right = a;
c->parent = a->parent;
a->parent = c;
return c;
}
// node is not the root
void insertRebuild(RBNode<T>* node)
{
RBNode<T>* parent = NULL;
RBNode<T>* grandParent = NULL;
while(node->parent != NULL)
{
parent = node->parent;
if(parent->color == RED)// here means there must be a grandparent
{
grandParent = parent->parent;
grandParent->color = BLACK;
if(grandParent->left == parent)
{
if(parent->left == node)
{
//LLRotate
node->color = BLACK;
node = LLRotate(grandParent,parent);
}
else
{
//LRRotate
parent->color = BLACK;
node = LRRotate(grandParent,parent,node);
}
}
else
{
if(parent->left == node)
{
//RLRotate
parent->color = BLACK;
node = RLRotate(grandParent,parent,node);
}
else
{
//RRRotate
node->color = BLACK;
node = RRRotate(grandParent,parent);
}
}
}
else
{
break;
}
}
if(node->parent == NULL)
{
node->color = BLACK;
this->root = node;
}
else
{
rebuild(node);
/*if(node->parent->data > node->data)
{
node->parent->left = node;
}
else
{
node->parent->right = node;
}*/
}
}
int getBlackNum(RBNode<T>* subRoot)
{
if(subRoot == NULL)
{
return 1;
}
int left = getBlackNum(subRoot->left);
int right = getBlackNum(subRoot->right);
if(left != right)
{
throw "wrong";
}
if(subRoot->color == BLACK)
{
return 1+left;
}
else
{
return left;
}
}
};
相关文章推荐
- 红黑树Red-Black-Tree
- 红黑树(Red Black Tree)
- 红黑树(Red Black Tree)
- 红黑树(red black tree)的实现
- RedBlackTree 红黑树——接力写
- 笔试算法题(51):简介 - 红黑树(RedBlack Tree)
- 红黑树(Red Black Tree)
- 红黑树(Red Black Tree)
- 红黑树(Red Black Tree)
- 红黑树(Red Black Tree)
- RedBlackTree(红黑树)--一种自平衡(最优)的二叉搜索树算法
- 《算法导论》读书笔记——红黑树(Red Black Tree)【for_wind】
- [转载] 红黑树(Red Black Tree)- 对于 JDK TreeMap的实现
- 红黑树(Red Black Tree)
- 红黑树(Red-Black Tree)
- 红黑树 RedBlackTree
- 红黑树(Red Black Tree)
- 红黑树—Red Black Tree
- 红黑树与C实现算法 - RedBlackTree.c
- 红黑树(Red Black Tree)