Browse Source

now it seems that rb trees are working now...stiff a lot of optimization work to be done, as this is mostly one 2 one the code from wikipedia, with some modifiations to work with NULL leaf nodes.

release0.1.5
Georg Hopp 12 years ago
parent
commit
c3498917bc
  1. 227
      src/rbtree.c

227
src/rbtree.c

@ -109,6 +109,8 @@ findInOrderSuccessor(struct element * tree)
return node; return node;
} }
void deleteOneChild(struct element **, struct element *);
void void
deleteElement(struct element ** tree, int data) deleteElement(struct element ** tree, int data)
{ {
@ -139,6 +141,10 @@ deleteElement(struct element ** tree, int data)
node = successor; node = successor;
} }
/*
* In rb trees we handle the remaining situations differently
*/
/*
// case 2: one child wither left or right // case 2: one child wither left or right
if (NULL != node->left) { if (NULL != node->left) {
//node->data = node->left->data; //node->data = node->left->data;
@ -186,6 +192,8 @@ deleteElement(struct element ** tree, int data)
} }
free(node); free(node);
*/
deleteOneChild(tree, node);
} }
@ -279,6 +287,16 @@ uncle(struct element * node)
return gp->left; return gp->left;
} }
struct element *
sibling(struct element * node)
{
if (node == node->parent->left)
return node->parent->right;
else
return node->parent->left;
}
void void
rotateLeft(struct element ** tree, struct element * node) rotateLeft(struct element ** tree, struct element * node)
{ {
@ -427,6 +445,173 @@ insertCase1(struct element ** tree, struct element * node)
} }
} }
void
replaceNode(struct element * node1, struct element * node2)
{
if (NULL != node1->parent) {
if (node1 == node1->parent->left) {
node1->parent->left = node2;
} else {
node1->parent->right = node2;
}
}
if (NULL != node2) {
node2->parent = node1->parent;
}
}
void
deleteCase6(struct element ** tree, struct element * node)
{
struct element * s = sibling(node);
s->color = node->parent->color;
node->parent->color = rbBlack;
if (node == node->parent->left) {
s->right->color = rbBlack;
rotateLeft(tree, node->parent);
} else {
s->left->color = rbBlack;
rotateRight(tree, node->parent);
}
}
void
deleteCase5(struct element ** tree, struct element * node)
{
struct element * s = sibling(node);
if (NULL != s && s->color == rbBlack) {
/*
* this if statement is trivial,
* due to case 2 (even though case 2 changed the sibling to a
* sibling's child,
* the sibling's child can't be red, since no red parent can
* have a red child).
*/
/*
* the following statements just force the red to be on the
* left of the left of the parent,
* or right of the right, so case six will rotate correctly.
*/
if ((node == node->parent->left) &&
(s->right->color == rbBlack) &&
(s->left->color == rbRed)) {
/* this last test is trivial too due to cases 2-4. */
s->color = rbRed;
s->left->color = rbBlack;
rotateRight(tree, s);
} else if ((node == node->parent->right) &&
(s->left->color == rbBlack) &&
(s->right->color == rbRed)) {
/*
* this last test is trivial too due to cases 2-4.
*/
s->color = rbRed;
s->right->color = rbBlack;
rotateLeft(tree, s);
}
}
deleteCase6(tree, node);
}
void
deleteCase4(struct element ** tree, struct element * node)
{
struct element * s = sibling(node);
if ((node->parent->color == rbRed) &&
(NULL == s || ((s->color == rbBlack) &&
(s->left->color == rbBlack) &&
(s->right->color == rbBlack)))) {
if (NULL != s) {
s->color = rbRed;
}
node->parent->color = rbBlack;
} else {
deleteCase5(tree, node);
}
}
void deleteCase1(struct element **, struct element *);
void
deleteCase3(struct element ** tree, struct element * node)
{
struct element * s = sibling(node);
if ((node->parent->color == rbBlack) &&
(NULL == s || ((s->color == rbBlack) &&
(s->left->color == rbBlack) &&
(s->right->color == rbBlack)))) {
if (NULL != s) {
s->color = rbRed;
}
deleteCase1(tree, node->parent);
} else {
deleteCase4(tree, node);
}
}
void
deleteCase2(struct element ** tree, struct element * node)
{
struct element * s = sibling(node);
if (NULL != s && s->color == rbRed) {
node->parent->color = rbRed;
s->color = rbBlack;
if (node == node->parent->left) {
rotateLeft(tree, node->parent);
} else {
rotateRight(tree, node->parent);
}
}
deleteCase3(tree, node);
}
void
deleteCase1(struct element ** tree, struct element * node)
{
if (NULL != node && NULL != node->parent) {
deleteCase2(tree, node);
}
}
void
deleteOneChild(struct element ** tree, struct element * node)
{
/*
* Precondition: n has at most one non-null child.
*/
struct element * child = (NULL == node->right) ? node->left : node->right;
replaceNode(node, child);
if (node->color == rbBlack) {
if (NULL != child && child->color == rbRed) {
child->color = rbBlack;
} else {
deleteCase1(tree, child);
}
}
if (NULL == node->parent){
*tree = 0x0;
}
free(node);
}
/** /**
* ======================================================================= * =======================================================================
*/ */
@ -479,16 +664,6 @@ main(int argc, char * argv[])
* Looks like the insert works properly. * Looks like the insert works properly.
* So the problem is out traversing... * So the problem is out traversing...
*/ */
// puts("elements:");
// for (i=1; i<20; i++) {
// struct element * element = findElement(root, i);
// printf("Element %02d: n=0x%p p=0x%p l=0x%p r=0x%p\n",
// i,
// element,
// element ? element->parent : 0x0,
// element ? element->left : 0x0,
// element ? element->right : 0x0);
// }
puts("traverse"); puts("traverse");
traverse(root1, printElement); traverse(root1, printElement);
@ -513,6 +688,38 @@ main(int argc, char * argv[])
puts("traverse"); puts("traverse");
traverse(root2, printElement); traverse(root2, printElement);
deleteElement(&root2, 8);
puts("traverse");
traverse(root2, printElement);
deleteElement(&root2, 11);
puts("traverse");
traverse(root2, printElement);
deleteElement(&root2, 13);
puts("traverse");
traverse(root2, printElement);
deleteElement(&root2, 3);
puts("traverse");
traverse(root2, printElement);
deleteElement(&root2, 16);
puts("traverse");
traverse(root2, printElement);
deleteElement(&root2, 10);
puts("traverse");
traverse(root2, printElement);
deleteElement(&root2, 9);
puts("traverse");
traverse(root2, printElement);
deleteElement(&root2, 12);
puts("traverse");
traverse(root2, printElement);
return 0; return 0;
} }

Loading…
Cancel
Save