Browse Source

all insert cases merged in one insertElement function.

release0.1.5
Georg Hopp 12 years ago
parent
commit
a543ed8538
  1. 406
      src/rbtree.c

406
src/rbtree.c

@ -50,40 +50,195 @@ findElement(struct element * tree, int data)
return tree;
}
/*
* function to get specific elements needed for
* rb handling, grandparent, uncle and sibbling
*/
struct element *
grandparent(struct element * node)
{
if (NULL != node && NULL != node->parent) {
return node->parent->parent;
}
return NULL;
}
struct element *
uncle(struct element * node)
{
struct element * gp = grandparent(node);
if (NULL == gp) {
return NULL;
}
if (node->parent == gp->left) {
return gp->right;
}
return gp->left;
}
struct element *
sibling(struct element * node)
{
return (node == node->parent->left) ?
node->parent->right :
node->parent->left;
}
/*
* rotations...also needed for rb handling.
*/
void
rotateLeft(struct element ** tree, struct element * node)
{
struct element * rightChild = node->right;
struct element * rcLeftSub = node->right->left;
rightChild->left = node;
rightChild->parent = node->parent;
node->right = rcLeftSub;
rcLeftSub->parent = node;
if (node->parent) {
if (node->parent->left == node) {
node->parent->left = rightChild;
} else {
node->parent->right = rightChild;
}
} else {
*tree = rightChild;
}
node->parent = rightChild;
}
void
rotateRight(struct element ** tree, struct element * node)
{
struct element * leftChild = node->left;
struct element * lcRightSub = node->left->right;
leftChild->right = node;
leftChild->parent = node->parent;
node->left = lcRightSub;
lcRightSub->parent = node;
if (node->parent) {
if (node->parent->left == node) {
node->parent->left = leftChild;
} else {
node->parent->right = leftChild;
}
} else {
*tree = leftChild;
}
node->parent = leftChild;
}
/**
* insert element in tree
*/
struct element *
insertElement(struct element ** tree, int data)
{
struct element * node = *tree;
struct element * node = *tree;
struct element * new_node = NULL;
struct element * u;
struct element * g;
// if tree is empty it's simple... :)
if (NULL == node) {
*tree = newElement(data);
return *tree;
*tree = node = new_node = newElement(data);
} else {
// normal binary tree add....
while (data != node->data) {
if (data < node->data) {
if (NULL == node->left) {
node->left = newElement(data);
node->left->parent = node;
new_node = node = node->left;
break;
} else {
node = node->left;
}
} else {
if (NULL == node->right) {
node->right = newElement(data);
node->right->parent = node;
new_node = node = node->right;
break;
} else {
node = node->right;
}
}
}
}
while (data != node->data) {
if (data < node->data) {
if (NULL == node->left) {
node->left = newElement(data);
node->left->parent = node;
return node->left;
} else {
if (NULL != new_node) {
/*
* handle reballancing rb style
*/
while (1) {
// case 1
if (node->parent == NULL) {
node->color = rbBlack;
// we're done.... :)
break;
}
// case 2
if (node->parent->color == rbBlack) {
// Tree is still valid ... wow, again we're done... :)
break;
}
// case 3
u = uncle(node);
g = grandparent(node);
if ((u != NULL) && (u->color == rbRed)) {
node->parent->color = rbBlack;
u->color = rbBlack;
g->color = rbRed;
node = g;
continue;
}
// case 4
if ((node == node->parent->right) && (node->parent == g->left)) {
rotateLeft(tree, node->parent);
node = node->left;
} else if (
(node == node->parent->left) &&
(node->parent == g->right)) {
rotateRight(tree, node->parent);
node = node->right;
}
} else {
if (NULL == node->right) {
node->right = newElement(data);
node->right->parent = node;
return node->right;
// case 5
g = grandparent(node);
node->parent->color = rbBlack;
g->color = rbRed;
if (node == node->parent->left) {
rotateRight(tree, g);
} else {
node = node->right;
rotateLeft(tree, g);
}
// we're done..
break;
}
}
return NULL;
return new_node;
}
/**
@ -205,194 +360,6 @@ void printElement(int data, int depth)
}
/*
* rbinsert from wikipedia...see later if this could be
* optiized.
*/
struct element *
grandparent(struct element * node)
{
if (NULL != node && NULL != node->parent) {
return node->parent->parent;
}
return NULL;
}
struct element *
uncle(struct element * node)
{
struct element * gp = grandparent(node);
if (NULL == gp) {
return NULL;
}
if (node->parent == gp->left) {
return gp->right;
}
return gp->left;
}
struct element *
sibling(struct element * node)
{
if (node == node->parent->left)
return node->parent->right;
else
return node->parent->left;
}
void
rotateLeft(struct element ** tree, struct element * node)
{
struct element * rightChild = node->right;
struct element * rcLeftSub = node->right->left;
rightChild->left = node;
rightChild->parent = node->parent;
node->right = rcLeftSub;
rcLeftSub->parent = node;
if (node->parent) {
if (node->parent->left == node) {
node->parent->left = rightChild;
} else {
node->parent->right = rightChild;
}
} else {
*tree = rightChild;
}
node->parent = rightChild;
}
void
rotateRight(struct element ** tree, struct element * node)
{
struct element * leftChild = node->left;
struct element * lcRightSub = node->left->right;
leftChild->right = node;
leftChild->parent = node->parent;
node->left = lcRightSub;
lcRightSub->parent = node;
if (node->parent) {
if (node->parent->left == node) {
node->parent->left = leftChild;
} else {
node->parent->right = leftChild;
}
} else {
*tree = leftChild;
}
node->parent = leftChild;
}
void
insertCase5(struct element ** tree, struct element * node)
{
struct element *g = grandparent(node);
node->parent->color = rbBlack;
g->color = rbRed;
if (node == node->parent->left) {
rotateRight(tree, g);
} else {
rotateLeft(tree, g);
}
}
void
insertCase4(struct element ** tree, struct element * node)
{
struct element * g = grandparent(node);
if ((node == node->parent->right) && (node->parent == g->left)) {
rotateLeft(tree, node->parent);
/*
* rotate_left can be the below because of already
* having *g = grandparent(n)
*
* struct node *saved_p=g->left, *saved_left_n=n->left;
* g->left=n;
* n->left=saved_p;
* saved_p->right=saved_left_n;
*
* and modify the parent's nodes properly
*/
node = node->left;
} else if (
(node == node->parent->left) &&
(node->parent == g->right)) {
rotateRight(tree, node->parent);
/*
* rotate_right can be the below to take advantage
* of already having *g = grandparent(n)
*
* struct node *saved_p=g->right, *saved_right_n=n->right;
* g->right=n;
* n->right=saved_p;
* saved_p->left=saved_right_n;
*
*/
node = node->right;
}
insertCase5(tree, node);
}
void insertCase1(struct element **, struct element *);
void
insertCase3(struct element ** tree, struct element * node)
{
struct element * u = uncle(node);
struct element * g;
if ((u != NULL) && (u->color == rbRed)) {
node->parent->color = rbBlack;
u->color = rbBlack;
g = grandparent(node);
g->color = rbRed;
insertCase1(tree, g);
} else {
insertCase4(tree, node);
}
}
void
insertCase2(struct element ** tree, struct element * node)
{
if (node->parent->color == rbBlack) {
return;
// Tree is still valid ... wow, again we're done... :)
} else {
insertCase3(tree, node);
}
}
void
insertCase1(struct element ** tree, struct element * node)
{
if (node->parent == NULL) {
node->color = rbBlack;
// we're done.... :)
} else {
insertCase2(tree, node);
}
}
void
replaceNode(struct element * node1, struct element * node2)
{
@ -568,28 +535,20 @@ int
main(int argc, char * argv[])
{
struct element * root = NULL;
struct element * inserted = NULL;
inserted = insertElement(&root, 13);
insertCase1(&root, inserted);
inserted = insertElement(&root, 8);
insertCase1(&root, inserted);
inserted = insertElement(&root, 16);
insertCase1(&root, inserted);
inserted = insertElement(&root, 11);
insertCase1(&root, inserted);
inserted = insertElement(&root, 3);
insertCase1(&root, inserted);
inserted = insertElement(&root, 9);
insertCase1(&root, inserted);
inserted = insertElement(&root, 12);
insertCase1(&root, inserted);
inserted = insertElement(&root, 10);
insertCase1(&root, inserted);
insertElement(&root, 13);
insertElement(&root, 8);
insertElement(&root, 16);
insertElement(&root, 11);
insertElement(&root, 3);
insertElement(&root, 9);
insertElement(&root, 12);
insertElement(&root, 10);
puts("traverse");
traverse(root, printElement);
/*
free(deleteElement(&root, 8));
puts("traverse");
traverse(root, printElement);
@ -621,6 +580,7 @@ main(int argc, char * argv[])
free(deleteElement(&root, 12));
puts("traverse");
traverse(root, printElement);
*/
return 0;
}

Loading…
Cancel
Save