#include <stdlib.h>
#include "rbtree.h"
typedef enum { BLACK, RED } NodeColor;
typedef struct NodeTag {
struct NodeTag *left; struct NodeTag *right; struct NodeTag *parent; NodeColor color; void *key; void *val; } NodeType;
typedef struct RbtTag {
NodeType *root; NodeType sentinel;
int (*compare)(void *a, void *b); } RbtType;
#define SENTINEL &rbt->sentinel
RbtHandle rbtNew(int(*rbtCompare)(void *a, void *b)) {
RbtType *rbt;
if ((rbt = (RbtType *)malloc(sizeof(RbtType))) == NULL) {
return NULL;
}
rbt->compare = rbtCompare;
rbt->root = SENTINEL;
rbt->sentinel.left = SENTINEL;
rbt->sentinel.right = SENTINEL;
rbt->sentinel.parent = NULL;
rbt->sentinel.color = BLACK;
rbt->sentinel.key = NULL;
rbt->sentinel.val = NULL;
return rbt;
}
static void deleteTree(RbtHandle h, NodeType *p) {
RbtType *rbt = h;
if (p == SENTINEL) return;
deleteTree(h, p->left);
deleteTree(h, p->right);
free(p);
}
void rbtDelete(RbtHandle h) {
RbtType *rbt = h;
deleteTree(h, rbt->root);
free(rbt);
}
static void rotateLeft(RbtType *rbt, NodeType *x) {
NodeType *y = x->right;
x->right = y->left;
if (y->left != SENTINEL) y->left->parent = x;
if (y != SENTINEL) y->parent = x->parent;
if (x->parent) {
if (x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
} else {
rbt->root = y;
}
y->left = x;
if (x != SENTINEL) x->parent = y;
}
static void rotateRight(RbtType *rbt, NodeType *x) {
NodeType *y = x->left;
x->left = y->right;
if (y->right != SENTINEL) y->right->parent = x;
if (y != SENTINEL) y->parent = x->parent;
if (x->parent) {
if (x == x->parent->right)
x->parent->right = y;
else
x->parent->left = y;
} else {
rbt->root = y;
}
y->right = x;
if (x != SENTINEL) x->parent = y;
}
static void insertFixup(RbtType *rbt, NodeType *x) {
while (x != rbt->root && x->parent->color == RED) {
if (x->parent == x->parent->parent->left) {
NodeType *y = x->parent->parent->right;
if (y->color == RED) {
x->parent->color = BLACK;
y->color = BLACK;
x->parent->parent->color = RED;
x = x->parent->parent;
} else {
if (x == x->parent->right) {
x = x->parent;
rotateLeft(rbt, x);
}
x->parent->color = BLACK;
x->parent->parent->color = RED;
rotateRight(rbt, x->parent->parent);
}
} else {
NodeType *y = x->parent->parent->left;
if (y->color == RED) {
x->parent->color = BLACK;
y->color = BLACK;
x->parent->parent->color = RED;
x = x->parent->parent;
} else {
if (x == x->parent->left) {
x = x->parent;
rotateRight(rbt, x);
}
x->parent->color = BLACK;
x->parent->parent->color = RED;
rotateLeft(rbt, x->parent->parent);
}
}
}
rbt->root->color = BLACK;
}
RbtStatus rbtInsert(RbtHandle h, void *key, void *val) {
NodeType *current, *parent, *x;
RbtType *rbt = h;
current = rbt->root;
parent = 0;
while (current != SENTINEL) {
int rc = rbt->compare(key, current->key);
if (rc == 0)
return RBT_STATUS_DUPLICATE_KEY;
parent = current;
current = (rc < 0) ? current->left : current->right;
}
if ((x = malloc (sizeof(*x))) == 0)
return RBT_STATUS_MEM_EXHAUSTED;
x->parent = parent;
x->left = SENTINEL;
x->right = SENTINEL;
x->color = RED;
x->key = key;
x->val = val;
if(parent) {
if(rbt->compare(key, parent->key) < 0)
parent->left = x;
else
parent->right = x;
} else {
rbt->root = x;
}
insertFixup(rbt, x);
return RBT_STATUS_OK;
}
static void deleteFixup(RbtType *rbt, NodeType *x) {
while (x != rbt->root && x->color == BLACK) {
if (x == x->parent->left) {
NodeType *w = x->parent->right;
if (w->color == RED) {
w->color = BLACK;
x->parent->color = RED;
rotateLeft (rbt, x->parent);
w = x->parent->right;
}
if (w->left->color == BLACK && w->right->color == BLACK) {
w->color = RED;
x = x->parent;
} else {
if (w->right->color == BLACK) {
w->left->color = BLACK;
w->color = RED;
rotateRight (rbt, w);
w = x->parent->right;
}
w->color = x->parent->color;
x->parent->color = BLACK;
w->right->color = BLACK;
rotateLeft (rbt, x->parent);
x = rbt->root;
}
} else {
NodeType *w = x->parent->left;
if (w->color == RED) {
w->color = BLACK;
x->parent->color = RED;
rotateRight (rbt, x->parent);
w = x->parent->left;
}
if (w->right->color == BLACK && w->left->color == BLACK) {
w->color = RED;
x = x->parent;
} else {
if (w->left->color == BLACK) {
w->right->color = BLACK;
w->color = RED;
rotateLeft (rbt, w);
w = x->parent->left;
}
w->color = x->parent->color;
x->parent->color = BLACK;
w->left->color = BLACK;
rotateRight (rbt, x->parent);
x = rbt->root;
}
}
}
x->color = BLACK;
}
RbtStatus rbtErase(RbtHandle h, RbtIterator i) {
NodeType *x, *y;
RbtType *rbt = h;
NodeType *z = i;
if (z->left == SENTINEL || z->right == SENTINEL) {
y = z;
} else {
y = z->right;
while (y->left != SENTINEL) y = y->left;
}
if (y->left != SENTINEL)
x = y->left;
else
x = y->right;
x->parent = y->parent;
if (y->parent)
if (y == y->parent->left)
y->parent->left = x;
else
y->parent->right = x;
else
rbt->root = x;
if (y != z) {
z->key = y->key;
z->val = y->val;
}
if (y->color == BLACK)
deleteFixup (rbt, x);
free (y);
return RBT_STATUS_OK;
}
RbtIterator rbtNext(RbtHandle h, RbtIterator it) {
RbtType *rbt = h;
NodeType *i = it;
if (i->right != SENTINEL) {
for (i = i->right; i->left != SENTINEL; i = i->left);
} else {
NodeType *p = i->parent;
while (p && i == p->right) {
i = p;
p = p->parent;
}
i = p;
}
return i != SENTINEL ? i : NULL;
}
RbtIterator rbtBegin(RbtHandle h) {
RbtType *rbt = h;
NodeType *i;
for (i = rbt->root; i->left != SENTINEL; i = i->left);
return i != SENTINEL ? i : NULL;
}
RbtIterator rbtEnd(RbtHandle h) {
return NULL;
}
void rbtKeyValue(RbtHandle h, RbtIterator it, void **key, void **val) {
NodeType *i = it;
*key = i->key;
*val = i->val;
}
void ** rbtValuePtr(RbtHandle h, RbtIterator it) {
NodeType *i = it;
return &i->val;
}
void *rbtFindLeftmost(RbtHandle h, void *key, int(*compare)(void *a, void *b))
{
RbtType *rbt = h;
NodeType *current = rbt->root;
NodeType *found = NULL;
while (current != SENTINEL) {
int rc = compare(key, current->key);
if (rc == 0) {
found = current;
current = current->left;
} else if (found) {
if (rc == 1)
current = current->right;
else
return found;
} else {
current = (rc < 0) ? current->left : current->right;
}
}
return found;
}
void *rbtFind(RbtHandle h, void *key) {
RbtType *rbt = h;
NodeType *current;
current = rbt->root;
while(current != SENTINEL) {
int rc = rbt->compare(key, current->key);
if (rc == 0) return current;
current = (rc < 0) ? current->left : current->right;
}
return NULL;
}
void rbtTraversal(RbtHandle h, RbtIterator it, void *handler_arg,
void(*handler)(void *arg, RbtIterator it)) {
RbtType *rbt = h;
NodeType *root = it;
handler(handler_arg, it);
if (root->left != SENTINEL)
rbtTraversal(h, root->left, handler_arg, handler);
if (root->right != SENTINEL)
rbtTraversal(h, root->right, handler_arg, handler);
}
void *rbtRoot(RbtHandle h) {
RbtType *rbt = h;
return rbt->root;
}