红黑树是一个比较常用到数据结构,是一个比AVL树有着更好的搜索能力的树形结构。
红黑树是一种自平衡二叉查找树
典型的用途是实现关联数组。它是复杂的,但它的操作有着良好的最坏情况运行时间,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n 是树中元素的数目。红黑树是一种很有意思的平衡检索树
它的统计性能要好于平衡二叉树(AVL-树),因此,红黑树在很多地方都有应用。在C++ STL中,很多部分(目前包括set, multiset, map, multimap)应用了红黑树的变体(SGI STL中的红黑树有一些变化,这些修改提供了更好的性能,以及对set操作的支持)。
红黑树的每个节点上的属性除了有一个key、3个指针:parent、lchild、rchild以外,还多了一个属性:color。它只能是两种颜色:红或黑。而红黑树除了具有二叉搜索树的所有性质之外,为了方便计算和统计节点的个数,增加了lcount和rcount。具有以下4点性质:
- 根节点是黑色的。
- 空节点是黑色的(红黑树中,根节点的parent以及所有叶节点lchild、rchild都不指向NULL,而是指向一个定义好的空节点)。
- 红色节点的父、左子、右子节点都是黑色。
- 在任何一棵子树中,每一条从根节点向下走到空节点的路径上包含的黑色节点数量都相同。
需要说明的是:红黑树并不是一个红黑交替的树型结构,第一红黑树的性质并没有保证说是不能有两个连续的黑色节点;第二在我们删除的时候是可能存在删除掉了红色节点, 是有可能有连续的两个黑色节点的可能。
#ifndef __RB_TREE_H
#define __RB_TREE_H
#include <iostream>
#include <functional>
struct key
{
int a;
};
typedef key KeyType;
struct RBTNode
{
bool color;
int lcount;
int rcount;
KeyType key;
RBTNode * leftchild;
RBTNode * rightchild;
RBTNode * parent;
};
class RBTree
{
public:
RBTree(RBTNode * p = NULL)
:m_root(NULL),
m_null(new RBTNode)
{
m_null->color = BLACK;
m_root = m_null;
}
~RBTree()
{
clear();
delete m_null;
}
bool insert(const KeyType & x)
{
RBTNode * node = new RBTNode;
node->key = x;
node->lcount = 0;
node->rcount = 0;
node->leftchild = m_null;
node->rightchild = m_null;
//node->parent = m_null;
node->color = RED; // new node should set red to keep
//each path has the number of black node
RBTNode * p = m_root;
RBTNode * leaf = m_null;
while ( p != m_null){ // find the leaf position
leaf = p;
if (keycmp (node->key,p->key) < 0){
p->lcount++;
p = p->leftchild;
} else if (keycmp(node->key,p->key) > 0){
p->rcount++;
p = p->rightchild;
} else if(keycmp(node->key,p->key) == 0) {
return false;
}
}
node->parent = leaf; // connection the tree of the leaf
if(leaf == m_null){
m_root = node;
} else if( keycmp( node->key,leaf->key) < 0){
leaf->leftchild = node;
} else {
leaf->rightchild = node;
}
insbalance(node);
return true;
}
bool del(const KeyType & x)
{
RBTNode *node = search(x);
if(node == NULL) return false;
RBTNode * toDel = node;
if(node->leftchild != m_null && node->rightchild != m_null){
toDel = Next(node);
} // double branch
RBTNode *p = toDel; // adujust the number of the child count
while (p->parent != m_null){
if(p == p->parent->leftchild){
p->parent->lcount--;
} else {
p->parent->rcount--;
}
p = p->parent;
} //end while adjust the number of the number
// single branch
RBTNode *replace = toDel->leftchild != m_null ?
toDel->leftchild:
toDel->rightchild;
replace->parent = toDel->parent; // find the parent node
if(replace->parent == m_null){ //m_root
m_root = replace;
} else if( toDel == toDel->parent->leftchild){
replace->parent->leftchild = replace;
} else {
replace->parent->rightchild = replace;
}
if(toDel != node ){ // replace the key value
node->key = toDel->key;
}
if(toDel->color == BLACK){ // this the only case ,need to reblace the tree
delbalance(replace);
}
delete toDel;
return true;
}
RBTNode *atIndex(int i)
{
RBTNode * result = m_root;
if( i > result->lcount + result->rcount){
return NULL;
} else {
while( i != result ->lcount){
if(i < result->lcount){
result = result->leftchild;
} else {
i -= result->lcount +1; // 直接掉过左分支
result = result->rightchild;
}
}
}
}
void toArray(int *arr)
{
RBTNode * p = Min();
int i = 0;
while (p != m_null){
arr[i++] = p->key.a;
p = Next(p);
}
}
RBTNode * Max() const
{
RBTNode * p = m_root;
while ( p->rightchild != m_null){
p = p->rightchild;
}
return p;
}
RBTNode* Min()const
{
RBTNode *p = m_root;
while (p->leftchild != NULL){
p = p->leftchild;
}
return p;
}
int size()const
{
return m_root != m_null ?
m_root->lcount + m_root->rcount + 1 : 0;
}
RBTNode * search(const KeyType & key)
{
RBTNode * p = m_root;
while( p != m_null && keycmp(key,p->key) != 0){
p = keycmp(key,p->key)<0 ? p->leftchild :p->rightchild;
}
return p == m_null ? NULL :p;
}
private:
void delbalance(RBTNode *node)
{
RBTNode *p = node;
while ( p != m_root && p->color == BLACK){
if(p == p->parent->leftchild){ // find the node of node's brother
RBTNode *sibling = p->parent->rightchild;
if(sibling->color == RED){ //
sibling->color = BLACK;
p->parent->color = RED;
leftRotate(p->parent);
sibling = p->parent->rightchild;
}
if(sibling->leftchild->color == BLACK &&
sibling->rightchild->color == BLACK){
sibling->color = RED;
p = p->parent;
} else {
if(sibling->rightchild->color == BLACK){
sibling->leftchild->color = BLACK;
sibling->color = RED;
rightRotate(sibling);
sibling = sibling->parent;
}
sibling->color = sibling ->parent->color;
sibling->parent->color = BLACK;
sibling->rightchild->color = BLACK;
leftRotate(sibling->parent);
p = m_root;
}
} else {
RBTNode *sibling = p->parent->leftchild;
if(sibling->color == RED){
sibling->color = BLACK;
p->parent->color = RED;
rightRotate(p->parent);
sibling = p->parent->leftchild;
}
if(sibling->leftchild->color == BLACK &&
sibling->rightchild->color == BLACK){
sibling->color = RED;
p = p->parent;
} else {
if(sibling->leftchild->color == BLACK){
sibling->rightchild->color = BLACK;
sibling->color = RED;
leftRotate(sibling);
sibling = sibling->parent;
}
sibling->color = sibling->parent->color;
sibling->parent->color = BLACK;
sibling->leftchild->color = BLACK;
rightRotate(sibling->parent);
p = m_root;
}
}
}
p->color = BLACK;
}
inline void leftRotate(RBTNode * node )
{
RBTNode *newroot = node->rightchild;
node->rightchild = newroot->leftchild;
node->rcount = newroot->lcount; // newroot left to node's right
newroot->leftchild->parent = node;
newroot->parent = node->parent;
if(newroot->parent == m_null){
m_root = newroot;
} else if(node == node->parent->leftchild){
node->parent->leftchild = newroot;
} else {
node->parent->rightchild = newroot;
}
newroot->leftchild = node;
newroot->lcount += node->lcount+1;
node->parent = newroot;
}
inline void rightRotate(RBTNode *node)
{
RBTNode * newroot = node->leftchild;
node->leftchild = newroot->rightchild;
node->lcount = newroot->rcount;
node->leftchild->parent = node;
newroot->parent = node->parent;
if(newroot->parent == m_null){
m_root = newroot;
} else if (node == node->parent->leftchild){
node->parent->leftchild = newroot;
} else {
node->parent->rightchild = newroot;
}
newroot->rightchild = node;
newroot->rcount += node->rcount +1;
node->parent = newroot;
}
void insbalance(RBTNode *node)
{
RBTNode *z = node;
while( z->parent->color == RED){
if(z->parent == z->parent->parent->leftchild){
RBTNode *uncle = z->parent->parent->rightchild;
if(uncle->color == RED){ // uncle is red ,to set the color of black: p->parent and uncle , set the p->parent->parent black
z->parent->color = BLACK;
uncle->color = BLACK;
z->parent->parent->color = RED;
z = z->parent->parent; // circle to the rebalance : z = z->parent->parent
} else {
if( z == z->parent->rightchild) { // if z is the right of the parent
z = z->parent;
leftRotate(z);
}
z->parent->color = BLACK;
z->parent->parent->color = RED;
rightRotate(z->parent->parent);
}
} else {
RBTNode *uncle = z->parent->parent->leftchild;
if(uncle->color == RED){
z->parent->color = BLACK;
uncle->color = BLACK;
z->parent->parent->color = RED;
z = z->parent->parent;
} else {
if( z == z->parent->leftchild){
z = z->parent;
rightRotate(z);
}
z->parent->color = BLACK;
z->parent->parent->color = RED;
leftRotate(z->parent->parent);
}
}
}
m_root->color = BLACK;
}
RBTNode *left(RBTNode * node)
{
RBTNode * result = node;
while (result ->leftchild != m_null){
result = result->leftchild;
}
return result;
}
RBTNode *right(RBTNode *node)
{
RBTNode * result = node;
while (result ->rightchild != m_null){
result = result->rightchild;
}
return result;
}
RBTNode *Next(RBTNode *node)
{
if(node == NULL) return NULL;
RBTNode * p = node;
if(p->rightchild != m_null){
p = left(p->rightchild);
} else {
p = node->parent;
RBTNode * temp = node;
while( p != m_null && temp == p->rightchild ){
temp = p;
p = p->parent;
}
}
return p;
}
RBTNode *Prev(RBTNode *node)
{
if(node == NULL ) return NULL;
RBTNode * result = node;
if(result ->leftchild != m_null){
result = left(result->rightchild);
} else {
result = node->parent;
RBTNode *temp = node;
while (result != m_null && temp == result->leftchild){
temp = result;
result = result->parent;
}
}
return result;
}
inline int keycmp(const KeyType & key1,const KeyType & key2)
{
return key1.a - key2.a;
}
void clear()
{
RBTNode * p = m_root;
while(p != m_null){
if(p->leftchild != m_null){
p = p->leftchild;
} else if ( p->rightchild != m_null){
p = p->rightchild;
} else {
RBTNode *temp = p;
p = p->parent;
if(temp == p->leftchild){
p->leftchild = m_null;
} else {
p->rightchild = m_null;
}
delete temp;
}
}
}
private:
const static bool RED = true;
const static bool BLACK = false;
RBTNode * m_root;
RBTNode * m_null;
};
#endif
简单的测试:
#include "RBTree.hpp"
#include <iostream>
using namespace std;
int main()
{
RBTree tree;
KeyType ar[] = {2,45,56,34,54,232,56,567,33,34,56,232,23,44};
int len = sizeof(ar)/sizeof(ar[0]);
for(int i = 0; i< len ;i++){
cout<<tree.insert(ar[i]);
}
cout<<endl;
for(int i = 0; i <len;i++){
cout<<tree.del(ar[i]);
}
return 0;
}
详细的解析请看附带的pdf文件