diff --git a/src/rbtree.c b/src/rbtree.c index 33a2e0c..b9d9a4e 100644 --- a/src/rbtree.c +++ b/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 { - node = node->left; + if (NULL != new_node) { + /* + * handle reballancing rb style + */ + while (1) { + // case 1 + if (node->parent == NULL) { + node->color = rbBlack; + // we're done.... :) + break; } - } else { - if (NULL == node->right) { - node->right = newElement(data); - node->right->parent = node; - return node->right; + + // 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; + } + + // 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; }