红黑树C++实现
参考CLRS第二版(ch 13)
#ifndef _C_RB_TREE_H_
#define _C_RB_TREE_H_
#define NULL 0
template <class KeyT, class DataT>
class RB_TREE{
public:
RB_TREE():root(NULL){}
void Insert(KeyT key, DataT data = NULL)
{
rb_nodes *node, *tmp;
node = root;
tmp = NULL;
while(node != NULL)
{
tmp = node;
if(key<node->key)
node = node->rb_left;
else if(key>node->key)
node = node->rb_right;
else
{
node->data = data;
return;
}
}
rb_nodes *newNode = new rb_nodes(key, data);
newNode->rb_parent = tmp;
if(tmp==NULL)
root = newNode;
else
{
if(key < tmp->key)
tmp->rb_left = newNode;
else
tmp->rb_right = newNode;
}
__rb_insert_fixup(newNode);
}
void Delete(KeyT key)
{
rb_nodes *node, *child, *parent;
Color color;
if(!(node = __rb_find_by_key(key)))return;
if(!node->rb_left||!node->rb_right)
{
if(!node->rb_left)
child = node->rb_right;
else
child = node->rb_left;
parent = node->rb_parent;
color = node->rb_color;
if(child)
child->rb_parent = parent;
if(parent)
{
if(parent->rb_left == node)
parent->rb_left = child;
else
parent->rb_right = child;
}
else
root = child;
delete node;
}
else // find successor node
{
rb_nodes *old = node;
node = node->rb_right;
while(node->rb_left != NULL)
node = node->rb_left;
child = node->rb_right;
parent = node->rb_parent;
color = node->rb_color;
if(child)
child->rb_parent = parent;
if(parent)
{
if(parent->rb_left == node)
parent->rb_left = child;
else
parent->rb_right = child;
}
else
root=child;
if(node->rb_parent == old)
parent = node;
node->rb_parent = old->rb_parent;
node->rb_color = old->rb_color;
node->rb_right = old->rb_right;
node->rb_left = old->rb_left;
if(old->rb_parent)
{
if(old->rb_parent->rb_left == old)
old->rb_parent->rb_left = node;
else
old->rb_parent->rb_right = node;
}
else
root = node;
old->rb_left->rb_parent = node;
if(old->rb_right)
old->rb_right->rb_parent = node;
delete old;
}
if(color == RB_BLACK)
__rb_delete_fixup(child, parent);
}
private:
enum Color{RB_RED,RB_BLACK};
class rb_nodes{
public:
rb_nodes(KeyT key, DataT data)
:rb_parent(NULL)
,rb_color(RB_RED)
,rb_left(NULL)
,rb_right(NULL)
{
this->key = key;
this->data = data;
}
rb_nodes *rb_parent;
Color rb_color;
rb_nodes *rb_left;
rb_nodes *rb_right;
KeyT key;
DataT data;
};
void __rb_rotate_left(rb_nodes *node)
{
rb_nodes *right = node->rb_right;
if((node->rb_right = right->rb_left) != NULL)
right->rb_left->rb_parent = node;
right->rb_left = node;
if((right->rb_parent = node->rb_parent) != NULL) // current node is not root
{
if(node == node->rb_parent->rb_left)
node->rb_parent->rb_left = right;
else
node->rb_parent->rb_right = right;
}
else
root = right;
node->rb_parent = right;
}
void __rb_rotate_right(rb_nodes *node)
{
rb_nodes *left = node->rb_left;
if((node->rb_left = left->rb_right) != NULL)
left->rb_right->rb_parent = node;
left->rb_right = node;
if((left->rb_parent = node->rb_parent) != NULL)
{
if(node == node->rb_parent->rb_left)
node->rb_parent->rb_left = left;
else
node->rb_parent->rb_right = left;
}
else
root = left;
node->rb_parent = left;
}
void __rb_insert_fixup(rb_nodes *node)
{
rb_nodes *parent, *gparent;
while((parent = node->rb_parent) && parent->rb_color == RB_RED)
{
gparent = parent->rb_parent;
if(parent == gparent->rb_left)
{
rb_nodes *uncle = gparent->rb_right;
if(uncle && uncle->rb_color == RB_RED)
{
uncle->rb_color = RB_BLACK;
parent->rb_color = RB_BLACK;
gparent->rb_color = RB_RED;
node = gparent;
continue;
}
if(parent->rb_right == node)
{
__rb_rotate_left(parent);
std::swap(parent, node);
}
parent->rb_color = RB_BLACK;
gparent->rb_color = RB_RED;
__rb_rotate_right(gparent);
}
else
{
rb_nodes *uncle = gparent->rb_left;
if(uncle && uncle->rb_color == RB_RED)
{
uncle->rb_color = RB_BLACK;
parent->rb_color = RB_BLACK;
gparent->rb_color = RB_RED;
node = gparent;
continue;
}
if(parent->rb_left == node)
{
__rb_rotate_right(parent);
std::swap(parent, node);
}
parent->rb_color = RB_BLACK;
gparent->rb_color = RB_RED;
__rb_rotate_left(gparent);
}
}
root->rb_color = RB_BLACK;
}
void __rb_delete_fixup(rb_nodes *node, rb_nodes *parent)
{
rb_nodes *other;
while((!node || node->rb_color == RB_BLACK) && node != root)
{
if (parent->rb_left == node)
{
other = parent->rb_right;
if(other->rb_color == RB_RED)
{
other->rb_color = RB_BLACK;
parent->rb_color = RB_RED;
__rb_rotate_left(parent);
other = parent->rb_right;
}
if((!other->rb_left || other->rb_left->rb_color == RB_BLACK)
&& (!other->rb_right || other->rb_right->rb_color == RB_BLACK))
{
other->rb_color = RB_RED;
node = parent;
parent = node->rb_parent;
}
else
{
if (!other->rb_right || other->rb_right->rb_color == RB_BLACK)
{
rb_nodes *tmp;
if((tmp = other->rb_left) != NULL)
tmp->rb_color = RB_BLACK;
other->rb_color = RB_RED;
__rb_rotate_right(other);
other = parent->rb_right;
}
other->rb_color = parent->rb_color;
parent->rb_color = RB_BLACK;
if(other->rb_right)
other->rb_right->rb_color = RB_BLACK;
__rb_rotate_left(parent);
node = root;
break;
}
}
else
{
other = parent->rb_left;
if(other->rb_color == RB_RED)
{
other->rb_color = RB_BLACK;
parent->rb_color = RB_RED;
__rb_rotate_right(parent);
other = parent->rb_left;
}
if((!other->rb_left || other->rb_left->rb_color == RB_BLACK)
&& (!other->rb_right || other->rb_right->rb_color == RB_BLACK))
{
other->rb_color = RB_RED;
node = parent;
parent = node->rb_parent;
}
else
{
if(!other->rb_left || other->rb_left->rb_color == RB_BLACK)
{
rb_nodes *tmp;
if((tmp = other->rb_right) != NULL)
tmp->rb_color = RB_RED;
__rb_rotate_left(other);
other = parent->rb_left;
}
other->rb_color = parent->rb_color;
parent->rb_color = RB_BLACK;
if(other->rb_left)
other->rb_left->rb_color = RB_BLACK;
__rb_rotate_right(parent);
node = root;
break;
}
}
}
if(node)
node->rb_color = RB_BLACK;
}
rb_nodes* __rb_find_by_key(KeyT key)
{
rb_nodes *node = root;
while(node)
{
if(key < node->key)
node = node->rb_left;
else if(key > node->key)
node = node->rb_right;
else
return node;
}
return NULL;
}
private:
rb_nodes *root;
};
#endif
Test:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include "crbtree.h"
#include <iostream>
using namespace std;
int main()
{
RB_TREE<int, int> rbtree;
rbtree.Insert(10, 100);
rbtree.Delete(10);
rbtree.Insert(10, 100);
rbtree.Insert(9, 100);
rbtree.Insert(15, 100);
rbtree.Insert(11, 100);
rbtree.Insert(3, 100);
rbtree.Insert(55, 100);
rbtree.Insert(8, 100);
rbtree.Insert(100, 100);
rbtree.Delete(15);
rbtree.Delete(8);
rbtree.Delete(9);
rbtree.Delete(3);
rbtree.Delete(10);
rbtree.Delete(3);
rbtree.Delete(55);
rbtree.Delete(100);
rbtree.Delete(11);
return 0;
}