Commit 07cb206931c6a135a0d038c7a6a06ceb5507d427
1 parent
af8994b0
Created a macro for tree find to prevent duplicating this code in insert and delete.
Showing
5 changed files
with
53 additions
and
80 deletions
| @@ -29,6 +29,27 @@ | @@ -29,6 +29,27 @@ | ||
| 29 | #define TR_TREE_LEFT(node) (NULL!=(node)?(node)->left:NULL) | 29 | #define TR_TREE_LEFT(node) (NULL!=(node)?(node)->left:NULL) |
| 30 | #define TR_TREE_PARENT(node) (NULL!=(node)?(node)->parent:NULL) | 30 | #define TR_TREE_PARENT(node) (NULL!=(node)?(node)->parent:NULL) |
| 31 | 31 | ||
| 32 | +/* | ||
| 33 | + * Find data in a tree. | ||
| 34 | + * Attention: This will change node, so normally you need to copy | ||
| 35 | + * it before using this macro. | ||
| 36 | + * Also be aware that found needs to be a valid lvalue and an integer. | ||
| 37 | + */ | ||
| 38 | +#define TR_TREE_FIND(node, search, found, comp) \ | ||
| 39 | + (found) = -1; \ | ||
| 40 | + while((node) && ((node)->left || (node)->right)) { \ | ||
| 41 | + (found) = (comp)((node)->data, (search)); \ | ||
| 42 | + if (0 != (found)) { \ | ||
| 43 | + if (0 < (found)) { \ | ||
| 44 | + (node) = (node)->left; \ | ||
| 45 | + } else { \ | ||
| 46 | + (node) = (node)->right; \ | ||
| 47 | + } \ | ||
| 48 | + } else { \ | ||
| 49 | + break; \ | ||
| 50 | + } \ | ||
| 51 | + } | ||
| 52 | + | ||
| 32 | #define TR_TREE_CHILD(node) \ | 53 | #define TR_TREE_CHILD(node) \ |
| 33 | (NULL==TR_TREE_RIGHT((node))?TR_TREE_LEFT((node)):TR_TREE_RIGHT((node))) | 54 | (NULL==TR_TREE_RIGHT((node))?TR_TREE_LEFT((node)):TR_TREE_RIGHT((node))) |
| 34 | 55 |
| @@ -28,35 +28,16 @@ TR_treeDelete(TR_Tree * this, const void * search, TR_TreeComp comp) | @@ -28,35 +28,16 @@ TR_treeDelete(TR_Tree * this, const void * search, TR_TreeComp comp) | ||
| 28 | { | 28 | { |
| 29 | TR_Tree node = *this; | 29 | TR_Tree node = *this; |
| 30 | TR_Tree del_node; | 30 | TR_Tree del_node; |
| 31 | + int found; | ||
| 31 | 32 | ||
| 32 | void * data; | 33 | void * data; |
| 33 | 34 | ||
| 34 | - /* | ||
| 35 | - * first search for it and if its found return the data | ||
| 36 | - * and we are done... | ||
| 37 | - */ | ||
| 38 | - while (NULL != node) { | ||
| 39 | - int comparison = comp(node->data, search); | ||
| 40 | - | ||
| 41 | - if (0 < comparison) { | ||
| 42 | - node = TR_TREE_LEFT(node); | ||
| 43 | - continue; | ||
| 44 | - } | ||
| 45 | - | ||
| 46 | - if (0 > comparison) { | ||
| 47 | - node = TR_TREE_RIGHT(node); | ||
| 48 | - continue; | ||
| 49 | - } | ||
| 50 | - | ||
| 51 | - if (0 == comparison) { | ||
| 52 | - break; | ||
| 53 | - } | ||
| 54 | - } | 35 | + TR_TREE_FIND(node, search, found, comp); |
| 55 | 36 | ||
| 56 | /* | 37 | /* |
| 57 | * nothing was found...return NULL to indicate this. | 38 | * nothing was found...return NULL to indicate this. |
| 58 | */ | 39 | */ |
| 59 | - if (NULL == node) { | 40 | + if (found != 0) { |
| 60 | return NULL; | 41 | return NULL; |
| 61 | } | 42 | } |
| 62 | 43 |
| @@ -25,25 +25,12 @@ | @@ -25,25 +25,12 @@ | ||
| 25 | void * | 25 | void * |
| 26 | TR_treeFind(TR_Tree this, const void * search, TR_TreeComp comp) | 26 | TR_treeFind(TR_Tree this, const void * search, TR_TreeComp comp) |
| 27 | { | 27 | { |
| 28 | - while (NULL != this) { | ||
| 29 | - int comparison = comp(this->data, search); | 28 | + TR_Tree node = this; |
| 29 | + int found; | ||
| 30 | 30 | ||
| 31 | - if (0 < comparison) { | ||
| 32 | - this = TR_TREE_LEFT(this); | ||
| 33 | - continue; | ||
| 34 | - } | 31 | + TR_TREE_FIND(node, search, found, comp); |
| 35 | 32 | ||
| 36 | - if (0 > comparison) { | ||
| 37 | - this = TR_TREE_RIGHT(this); | ||
| 38 | - continue; | ||
| 39 | - } | ||
| 40 | - | ||
| 41 | - if (0 == comparison) { | ||
| 42 | - break; | ||
| 43 | - } | ||
| 44 | - } | ||
| 45 | - | ||
| 46 | - return NULL != this ? this->data : NULL; | 33 | + return found == 0 ? node->data : NULL; |
| 47 | } | 34 | } |
| 48 | 35 | ||
| 49 | // vim: set ts=4 sw=4: | 36 | // vim: set ts=4 sw=4: |
| @@ -28,6 +28,9 @@ TR_treeInsert(TR_Tree * this, const void * search, TR_TreeComp comp) | @@ -28,6 +28,9 @@ TR_treeInsert(TR_Tree * this, const void * search, TR_TreeComp comp) | ||
| 28 | { | 28 | { |
| 29 | TR_Tree node = *this; | 29 | TR_Tree node = *this; |
| 30 | TR_Tree new_node = NULL; | 30 | TR_Tree new_node = NULL; |
| 31 | + int found; | ||
| 32 | + | ||
| 33 | + TR_TREE_FIND(node, search, found, comp); | ||
| 31 | 34 | ||
| 32 | /* | 35 | /* |
| 33 | * insert the node or return the one in tree if comparison | 36 | * insert the node or return the one in tree if comparison |
| @@ -40,43 +43,24 @@ TR_treeInsert(TR_Tree * this, const void * search, TR_TreeComp comp) | @@ -40,43 +43,24 @@ TR_treeInsert(TR_Tree * this, const void * search, TR_TreeComp comp) | ||
| 40 | */ | 43 | */ |
| 41 | *this = node = new_node = TR_new(TR_Tree, search); | 44 | *this = node = new_node = TR_new(TR_Tree, search); |
| 42 | } else { | 45 | } else { |
| 43 | - /* | ||
| 44 | - * first search for it and if its found return the data | ||
| 45 | - * and we are done... | ||
| 46 | - */ | ||
| 47 | - while (NULL != node) { | ||
| 48 | - int comparison = comp(node->data, search); | ||
| 49 | - | ||
| 50 | - if (0 < comparison) { | ||
| 51 | - if (NULL != TR_TREE_LEFT(node)) { | ||
| 52 | - node = TR_TREE_LEFT(node); | ||
| 53 | - continue; | ||
| 54 | - } else { | ||
| 55 | - node->left = TR_new(TR_Tree, search); | ||
| 56 | - node->left->parent = node; | ||
| 57 | - node = new_node = node->left; | ||
| 58 | - break; | ||
| 59 | - } | ||
| 60 | - } | ||
| 61 | - | ||
| 62 | - if (0 > comparison) { | ||
| 63 | - if (NULL != TR_TREE_RIGHT(node)) { | ||
| 64 | - node = TR_TREE_RIGHT(node); | ||
| 65 | - continue; | ||
| 66 | - } else { | ||
| 67 | - node->right = TR_new(TR_Tree, search); | ||
| 68 | - node->right->parent = node; | ||
| 69 | - node = new_node = node->right; | ||
| 70 | - break; | ||
| 71 | - } | ||
| 72 | - } | ||
| 73 | - | ||
| 74 | - if (0 == comparison) { | ||
| 75 | - // as this is insert and not find this will overwrite an existing value, | ||
| 76 | - // but return the previos one so that it can be freed if neccessary. | ||
| 77 | - void * data = node->data; | ||
| 78 | - node->data = (void *)search; | ||
| 79 | - return data; | 46 | + if (found == 0) { |
| 47 | + // we found an element | ||
| 48 | + // as this is insert and not find this will overwrite an existing | ||
| 49 | + // value, but return the previous one so that it can be freed if | ||
| 50 | + // neccessary. | ||
| 51 | + void * data = node->data; | ||
| 52 | + node->data = (void *)search; | ||
| 53 | + return data; | ||
| 54 | + } else { | ||
| 55 | + // not found | ||
| 56 | + if (0 < found) { | ||
| 57 | + node->left = TR_new(TR_Tree, search); | ||
| 58 | + node->left->parent = node; | ||
| 59 | + node = new_node = node->left; | ||
| 60 | + } else { | ||
| 61 | + node->right = TR_new(TR_Tree, search); | ||
| 62 | + node->right->parent = node; | ||
| 63 | + node = new_node = node->right; | ||
| 80 | } | 64 | } |
| 81 | } | 65 | } |
| 82 | } | 66 | } |
| @@ -114,13 +98,13 @@ TR_treeInsert(TR_Tree * this, const void * search, TR_TreeComp comp) | @@ -114,13 +98,13 @@ TR_treeInsert(TR_Tree * this, const void * search, TR_TreeComp comp) | ||
| 114 | && node->parent == node->parent->parent->left) { | 98 | && node->parent == node->parent->parent->left) { |
| 115 | 99 | ||
| 116 | TR_TREE_ROTATE(left, this, node->parent); | 100 | TR_TREE_ROTATE(left, this, node->parent); |
| 117 | - node = TR_TREE_LEFT(node); | 101 | + node = node->left; |
| 118 | 102 | ||
| 119 | } else if (node == node->parent->left | 103 | } else if (node == node->parent->left |
| 120 | && node->parent == node->parent->parent->right) { | 104 | && node->parent == node->parent->parent->right) { |
| 121 | 105 | ||
| 122 | TR_TREE_ROTATE(right, this, node->parent); | 106 | TR_TREE_ROTATE(right, this, node->parent); |
| 123 | - node = TR_TREE_RIGHT(node); | 107 | + node = node->right; |
| 124 | 108 | ||
| 125 | } | 109 | } |
| 126 | 110 |
| @@ -11,13 +11,13 @@ | @@ -11,13 +11,13 @@ | ||
| 11 | #define HAVE_MEMORY_H 1 | 11 | #define HAVE_MEMORY_H 1 |
| 12 | 12 | ||
| 13 | /* Define to 1 if you have the `memset' function. */ | 13 | /* Define to 1 if you have the `memset' function. */ |
| 14 | -/* #undef HAVE_MEMSET */ | 14 | +#define HAVE_MEMSET 1 |
| 15 | 15 | ||
| 16 | /* Define to 1 if you have the <stdarg.h> header file. */ | 16 | /* Define to 1 if you have the <stdarg.h> header file. */ |
| 17 | #define HAVE_STDARG_H 1 | 17 | #define HAVE_STDARG_H 1 |
| 18 | 18 | ||
| 19 | /* Define to 1 if stdbool.h conforms to C99. */ | 19 | /* Define to 1 if stdbool.h conforms to C99. */ |
| 20 | -/* #undef HAVE_STDBOOL_H */ | 20 | +#define HAVE_STDBOOL_H 1 |
| 21 | 21 | ||
| 22 | /* Define to 1 if you have the <stdint.h> header file. */ | 22 | /* Define to 1 if you have the <stdint.h> header file. */ |
| 23 | #define HAVE_STDINT_H 1 | 23 | #define HAVE_STDINT_H 1 |
Please
register
or
login
to post a comment