#include "hev-rbtree.h"
typedef enum _HevRBTreeColor HevRBTreeColor;
enum _HevRBTreeColor
{
HEV_RBTREE_RED = 0,
HEV_RBTREE_BLACK,
};
static inline int
hev_rbtree_node_color (HevRBTreeNode *node)
{
return node->__parent_color & 1;
}
static inline int
hev_rbtree_node_is_red (HevRBTreeNode *node)
{
return !(hev_rbtree_node_color (node) & HEV_RBTREE_BLACK);
}
static inline int
hev_rbtree_node_is_black (HevRBTreeNode *node)
{
return hev_rbtree_node_color (node) & HEV_RBTREE_BLACK;
}
static inline int
_hev_rbtree_node_is_black (unsigned long pc)
{
return pc & HEV_RBTREE_BLACK;
}
static inline HevRBTreeNode *
_hev_rbtree_node_parent (unsigned long pc)
{
return ((HevRBTreeNode *)(pc & ~3));
}
static inline HevRBTreeNode *
hev_rbtree_node_red_parent (HevRBTreeNode *node)
{
return (HevRBTreeNode *)node->__parent_color;
}
static inline void
hev_rbtree_node_set_black (HevRBTreeNode *node)
{
node->__parent_color |= HEV_RBTREE_BLACK;
}
static inline void
hev_rbtree_node_set_parent (HevRBTreeNode *node, HevRBTreeNode *parent)
{
node->__parent_color = hev_rbtree_node_color (node) | (unsigned long)parent;
}
static inline void
hev_rbtree_node_set_parent_color (HevRBTreeNode *node, HevRBTreeNode *parent,
int color)
{
node->__parent_color = (unsigned long)parent | color;
}
static inline void
hev_rbtree_change_child (HevRBTree *self, HevRBTreeNode *old,
HevRBTreeNode *new, HevRBTreeNode *parent)
{
if (parent) {
if (parent->left == old)
parent->left = new;
else
parent->right = new;
} else {
self->root = new;
}
}
static inline void
hev_rbtree_rotate_set_parents (HevRBTree *self, HevRBTreeNode *old,
HevRBTreeNode *new, int color)
{
HevRBTreeNode *parent = hev_rbtree_node_parent (old);
new->__parent_color = old->__parent_color;
hev_rbtree_node_set_parent_color (old, new, color);
hev_rbtree_change_child (self, old, new, parent);
}
HevRBTreeNode *
hev_rbtree_node_prev (HevRBTreeNode *node)
{
HevRBTreeNode *parent;
if (hev_rbtree_node_empty (node))
return NULL;
if (node->left) {
node = node->left;
while (node->right)
node = node->right;
return (HevRBTreeNode *)node;
}
while ((parent = hev_rbtree_node_parent (node)) && node == parent->left)
node = parent;
return parent;
}
HevRBTreeNode *
hev_rbtree_node_next (HevRBTreeNode *node)
{
HevRBTreeNode *parent;
if (hev_rbtree_node_empty (node))
return NULL;
if (node->right) {
node = node->right;
while (node->left)
node = node->left;
return (HevRBTreeNode *)node;
}
while ((parent = hev_rbtree_node_parent (node)) && node == parent->right)
node = parent;
return parent;
}
HevRBTreeNode *
hev_rbtree_first (HevRBTree *self)
{
HevRBTreeNode *n;
n = self->root;
if (!n)
return NULL;
while (n->left)
n = n->left;
return n;
}
HevRBTreeNode *
hev_rbtree_last (HevRBTree *self)
{
HevRBTreeNode *n;
n = self->root;
if (!n)
return NULL;
while (n->right)
n = n->right;
return n;
}
void
hev_rbtree_insert_color (HevRBTree *self, HevRBTreeNode *node)
{
HevRBTreeNode *parent = hev_rbtree_node_red_parent (node), *gparent, *tmp;
while (1) {
if (!parent) {
hev_rbtree_node_set_parent_color (node, NULL, HEV_RBTREE_BLACK);
break;
}
if (hev_rbtree_node_is_black (parent))
break;
gparent = hev_rbtree_node_red_parent (parent);
tmp = gparent->right;
if (parent != tmp) {
if (tmp && hev_rbtree_node_is_red (tmp)) {
hev_rbtree_node_set_parent_color (tmp, gparent,
HEV_RBTREE_BLACK);
hev_rbtree_node_set_parent_color (parent, gparent,
HEV_RBTREE_BLACK);
node = gparent;
parent = hev_rbtree_node_parent (node);
hev_rbtree_node_set_parent_color (node, parent, HEV_RBTREE_RED);
continue;
}
tmp = parent->right;
if (node == tmp) {
tmp = node->left;
parent->right = tmp;
node->left = parent;
if (tmp)
hev_rbtree_node_set_parent_color (tmp, parent,
HEV_RBTREE_BLACK);
hev_rbtree_node_set_parent_color (parent, node, HEV_RBTREE_RED);
parent = node;
tmp = node->right;
}
gparent->left = tmp;
parent->right = gparent;
if (tmp)
hev_rbtree_node_set_parent_color (tmp, gparent,
HEV_RBTREE_BLACK);
hev_rbtree_rotate_set_parents (self, gparent, parent,
HEV_RBTREE_RED);
break;
} else {
tmp = gparent->left;
if (tmp && hev_rbtree_node_is_red (tmp)) {
hev_rbtree_node_set_parent_color (tmp, gparent,
HEV_RBTREE_BLACK);
hev_rbtree_node_set_parent_color (parent, gparent,
HEV_RBTREE_BLACK);
node = gparent;
parent = hev_rbtree_node_parent (node);
hev_rbtree_node_set_parent_color (node, parent, HEV_RBTREE_RED);
continue;
}
tmp = parent->left;
if (node == tmp) {
tmp = node->right;
parent->left = tmp;
node->right = parent;
if (tmp)
hev_rbtree_node_set_parent_color (tmp, parent,
HEV_RBTREE_BLACK);
hev_rbtree_node_set_parent_color (parent, node, HEV_RBTREE_RED);
parent = node;
tmp = node->left;
}
gparent->right = tmp;
parent->left = gparent;
if (tmp)
hev_rbtree_node_set_parent_color (tmp, gparent,
HEV_RBTREE_BLACK);
hev_rbtree_rotate_set_parents (self, gparent, parent,
HEV_RBTREE_RED);
break;
}
}
}
void
hev_rbtree_replace (HevRBTree *self, HevRBTreeNode *victim, HevRBTreeNode *new)
{
HevRBTreeNode *parent = hev_rbtree_node_parent (victim);
*new = *victim;
if (victim->left)
hev_rbtree_node_set_parent (victim->left, new);
if (victim->right)
hev_rbtree_node_set_parent (victim->right, new);
hev_rbtree_change_child (self, victim, new, parent);
}
static inline HevRBTreeNode *
_hev_rbtree_erase (HevRBTree *self, HevRBTreeNode *node)
{
HevRBTreeNode *child = node->right;
HevRBTreeNode *tmp = node->left;
HevRBTreeNode *parent, *rebalance;
unsigned long pc;
if (!tmp) {
pc = node->__parent_color;
parent = _hev_rbtree_node_parent (pc);
hev_rbtree_change_child (self, node, child, parent);
if (child) {
child->__parent_color = pc;
rebalance = NULL;
} else
rebalance = _hev_rbtree_node_is_black (pc) ? parent : NULL;
tmp = parent;
} else if (!child) {
tmp->__parent_color = pc = node->__parent_color;
parent = _hev_rbtree_node_parent (pc);
hev_rbtree_change_child (self, node, tmp, parent);
rebalance = NULL;
tmp = parent;
} else {
HevRBTreeNode *successor = child, *child2;
tmp = child->left;
if (!tmp) {
parent = successor;
child2 = successor->right;
} else {
do {
parent = successor;
successor = tmp;
tmp = tmp->left;
} while (tmp);
child2 = successor->right;
parent->left = child2;
successor->right = child;
hev_rbtree_node_set_parent (child, successor);
}
tmp = node->left;
successor->left = tmp;
hev_rbtree_node_set_parent (tmp, successor);
pc = node->__parent_color;
tmp = _hev_rbtree_node_parent (pc);
hev_rbtree_change_child (self, node, successor, tmp);
if (child2) {
hev_rbtree_node_set_parent_color (child2, parent, HEV_RBTREE_BLACK);
rebalance = NULL;
} else {
rebalance = hev_rbtree_node_is_black (successor) ? parent : NULL;
}
successor->__parent_color = pc;
tmp = successor;
}
return rebalance;
}
static inline void
_hev_rbtree_erase_color (HevRBTree *self, HevRBTreeNode *parent)
{
HevRBTreeNode *node = NULL, *sibling, *tmp1, *tmp2;
while (1) {
sibling = parent->right;
if (node != sibling) {
if (hev_rbtree_node_is_red (sibling)) {
tmp1 = sibling->left;
parent->right = tmp1;
sibling->left = parent;
hev_rbtree_node_set_parent_color (tmp1, parent,
HEV_RBTREE_BLACK);
hev_rbtree_rotate_set_parents (self, parent, sibling,
HEV_RBTREE_RED);
sibling = tmp1;
}
tmp1 = sibling->right;
if (!tmp1 || hev_rbtree_node_is_black (tmp1)) {
tmp2 = sibling->left;
if (!tmp2 || hev_rbtree_node_is_black (tmp2)) {
hev_rbtree_node_set_parent_color (sibling, parent,
HEV_RBTREE_RED);
if (hev_rbtree_node_is_red (parent))
hev_rbtree_node_set_black (parent);
else {
node = parent;
parent = hev_rbtree_node_parent (node);
if (parent)
continue;
}
break;
}
tmp1 = tmp2->right;
sibling->left = tmp1;
tmp2->right = sibling;
parent->right = tmp2;
if (tmp1)
hev_rbtree_node_set_parent_color (tmp1, sibling,
HEV_RBTREE_BLACK);
tmp1 = sibling;
sibling = tmp2;
}
tmp2 = sibling->left;
parent->right = tmp2;
sibling->left = parent;
hev_rbtree_node_set_parent_color (tmp1, sibling, HEV_RBTREE_BLACK);
if (tmp2)
hev_rbtree_node_set_parent (tmp2, parent);
hev_rbtree_rotate_set_parents (self, parent, sibling,
HEV_RBTREE_BLACK);
break;
} else {
sibling = parent->left;
if (hev_rbtree_node_is_red (sibling)) {
tmp1 = sibling->right;
parent->left = tmp1;
sibling->right = parent;
hev_rbtree_node_set_parent_color (tmp1, parent,
HEV_RBTREE_BLACK);
hev_rbtree_rotate_set_parents (self, parent, sibling,
HEV_RBTREE_RED);
sibling = tmp1;
}
tmp1 = sibling->left;
if (!tmp1 || hev_rbtree_node_is_black (tmp1)) {
tmp2 = sibling->right;
if (!tmp2 || hev_rbtree_node_is_black (tmp2)) {
hev_rbtree_node_set_parent_color (sibling, parent,
HEV_RBTREE_RED);
if (hev_rbtree_node_is_red (parent))
hev_rbtree_node_set_black (parent);
else {
node = parent;
parent = hev_rbtree_node_parent (node);
if (parent)
continue;
}
break;
}
tmp1 = tmp2->left;
sibling->right = tmp1;
tmp2->left = sibling;
parent->left = tmp2;
if (tmp1)
hev_rbtree_node_set_parent_color (tmp1, sibling,
HEV_RBTREE_BLACK);
tmp1 = sibling;
sibling = tmp2;
}
tmp2 = sibling->right;
parent->left = tmp2;
sibling->right = parent;
hev_rbtree_node_set_parent_color (tmp1, sibling, HEV_RBTREE_BLACK);
if (tmp2)
hev_rbtree_node_set_parent (tmp2, parent);
hev_rbtree_rotate_set_parents (self, parent, sibling,
HEV_RBTREE_BLACK);
break;
}
}
}
void
hev_rbtree_erase (HevRBTree *self, HevRBTreeNode *node)
{
HevRBTreeNode *rebalance;
rebalance = _hev_rbtree_erase (self, node);
if (rebalance)
_hev_rbtree_erase_color (self, rebalance);
}