1 changed files with 297 additions and 0 deletions
-
297src/rbtree.c
@ -0,0 +1,297 @@ |
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
|
|||
|
|||
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; i<depth-1; i++) printf("-"); |
|||
printf("%02d(%02d)\n", data, depth); |
|||
} |
|||
|
|||
/** |
|||
* ======================================================================= |
|||
*/ |
|||
int |
|||
main(int argc, char * argv[]) |
|||
{ |
|||
int i; |
|||
struct element * root = NULL; |
|||
|
|||
insertElement(&root, 13); |
|||
insertElement(&root, 8); |
|||
insertElement(&root, 16); |
|||
insertElement(&root, 11); |
|||
insertElement(&root, 3); |
|||
insertElement(&root, 9); |
|||
insertElement(&root, 12); |
|||
insertElement(&root, 10); |
|||
|
|||
/* |
|||
* after this I have the following: |
|||
* |
|||
* Element 03: n=0x0xcf50d0 p=0x0xcf5040 l=0x(nil) r=0x(nil) |
|||
* Element 08: n=0x0xcf5040 p=0x0xcf5010 l=0x0xcf50d0 r=0x0xcf50a0 |
|||
* Element 09: n=0x0xcf5100 p=0x0xcf50a0 l=0x(nil) r=0x0xcf5160 |
|||
* Element 10: n=0x0xcf5160 p=0x0xcf5100 l=0x(nil) r=0x(nil) |
|||
* Element 11: n=0x0xcf50a0 p=0x0xcf5040 l=0x0xcf5100 r=0x0xcf5130 |
|||
* Element 12: n=0x0xcf5130 p=0x0xcf50a0 l=0x(nil) r=0x(nil) |
|||
* Element 13: n=0x0xcf5010 p=0x(nil) l=0x0xcf5040 r=0x0xcf5070 |
|||
* Element 16: n=0x0xcf5070 p=0x0xcf5010 l=0x(nil) r=0x(nil) |
|||
* |
|||
* which translates to: |
|||
* |
|||
* 03 has p:08, l:N , R:N |
|||
* 08 has p:13, l:03, r:11 |
|||
* 09 has p:11, l:N , r:10 |
|||
* 10 has p:09, l:N , r:N |
|||
* 11 has p:08, l:09, r:12 |
|||
* 12 has p:11, l:N , r:N |
|||
* 13 has p:N , l:08, r:16 |
|||
* 16 has p:13, l:N , r:N |
|||
* |
|||
* which visualizes as: |
|||
* 13 |
|||
* 08 16 |
|||
* 03 11 0 0 |
|||
* 0 0 09 12 |
|||
* 0 10 0 0 |
|||
* |
|||
* Looks like the insert works properly. |
|||
* 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"); |
|||
traverse(root, printElement); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
// vim: set et ts=4 sw=4: |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue