From fafc5af2abd04bd8b7c644c3c9be93ae5e019625 Mon Sep 17 00:00:00 2001 From: Georg Hopp Date: Fri, 23 Aug 2013 11:24:01 +0100 Subject: [PATCH] cope binarytree to play with an rbtree implementation --- src/rbtree.c | 297 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 297 insertions(+) create mode 100644 src/rbtree.c diff --git a/src/rbtree.c b/src/rbtree.c new file mode 100644 index 0000000..68b7ad2 --- /dev/null +++ b/src/rbtree.c @@ -0,0 +1,297 @@ +#include +#include + + +struct element +{ + int data; + + struct element * parent; + struct element * left; + struct element * right; +}; + +struct element * +newElement(int data) +{ + struct element * el = malloc(sizeof(struct element)); + el->data = data; + el->parent = NULL; + el->left = NULL; + el->right = NULL; + + return el; +} + +/** + * find element in tree + */ +struct element * +findElement(struct element * tree, int data) +{ + while (NULL != tree) { + if (tree->data == data) { + break; + } + + if (data < tree->data) { + tree = tree->left; + } else { + tree = tree->right; + } + } + + return tree; +} + +/** + * insert element in tree + */ +void +insertElement(struct element ** tree, int data) +{ + struct element * node = *tree; + + if (NULL == node) { + *tree = newElement(data); + return; + } + + while (data != node->data) { + if (data < node->data) { + if (NULL == node->left) { + node->left = newElement(data); + node->left->parent = node; + return; + } else { + node = node->left; + } + } else { + if (NULL == node->right) { + node->right = newElement(data); + node->right->parent = node; + return; + } else { + node = node->right; + } + } + } +} + +/** + * delete element from tree + * here multiple functions are involved.... + * ======================================================================= + */ +/** + * find minimum of the right subtree aka leftmost leaf of right subtree + * aka left in-order successor. + * We return the parent of the element in the out argument parent. + * This can be NULL wenn calling. + */ +struct element * +findInOrderSuccessor(struct element * tree) +{ + struct element * node = tree->right; + + while (NULL != node->left) { + node = node->left; + } + + return node; +} + +void +deleteElement(struct element ** tree, int data) +{ + struct element * node = *tree; + + // find the relevant node and it's parent + while (NULL != node && node->data != data) { + if (data < node->data) { + node = node->left; + } else { + node = node->right; + } + } + + // element not found + if (NULL == node) { + return; + } + + // distinuish 3 cases, where the resolving of each case leads to the + // precondition of the other. + + // case 1: two children + if (NULL != node->left && NULL != node->right) { + struct element * successor = findInOrderSuccessor(node); + + node->data = successor->data; + node = successor; + } + + // case 2: one child wither left or right + if (NULL != node->left) { + //node->data = node->left->data; + //node = node->left; + if (NULL != node->parent) { + if (node == node->parent->left) { + node->parent->left = node->left; + } else { + node->parent->right = node->left; + } + } + node->left->parent = node->parent; + } + + if (NULL != node->right) { + //node->data = node->right->data; + //node = node->right; + if (NULL != node->parent) { + if (node == node->parent->left) { + node->parent->left = node->right; + } else { + node->parent->right = node->right; + } + } + node->right->parent = node->parent; + } + + // case 3: we are a leaf + if (NULL != node->parent) { + if (node == node->parent->left) { + node->parent->left = NULL; + } else { + node->parent->right = NULL; + } + } + + if (node == *tree) { + if (NULL != node->left) { + *tree = node->left; + } else if (NULL != node->right) { + *tree = node->right; + } else { + *tree = NULL; + } + } + + free(node); +} + + +void +traverse(struct element * tree, void (*cb)(int, int)) +{ + struct element * previous = tree; + struct element * node = tree; + int depth = 1; + + // I think this has something like O(n+log(n)) on a ballanced + // tree because I have to traverse back the rightmost leaf to + // the root to get a break condition. + while (node) { + if (previous == node->right) { + previous = node; + node = node->parent; + depth--; + continue; + } + + if ((NULL == node->left || previous == node->left)) { + cb(node->data, depth); + previous = node; + + if (NULL != node->right) { + node = node->right; + depth++; + } else { + node = node->parent; + depth--; + } + } else { + previous = node; + node = node->left; + depth++; + } + } +} + +void printElement(int data, int depth) +{ + int i; + + for (i=0; iparent : 0x0, + element ? element->left : 0x0, + element ? element->right : 0x0); + } + + puts("traverse"); + traverse(root, printElement); + + return 0; +} + +// vim: set et ts=4 sw=4: