From 07cb206931c6a135a0d038c7a6a06ceb5507d427 Mon Sep 17 00:00:00 2001 From: Georg Hopp Date: Sat, 21 Jun 2014 20:13:25 +0100 Subject: [PATCH] Created a macro for tree find to prevent duplicating this code in insert and delete. --- include/tr/tree.h | 21 ++++++++++++++++ src/tree/delete.c | 25 +++---------------- src/tree/find.c | 21 +++------------- src/tree/insert.c | 62 ++++++++++++++++++----------------------------- trdata.h | 4 +-- 5 files changed, 53 insertions(+), 80 deletions(-) diff --git a/include/tr/tree.h b/include/tr/tree.h index 5ab1b96..1fbf230 100644 --- a/include/tr/tree.h +++ b/include/tr/tree.h @@ -29,6 +29,27 @@ #define TR_TREE_LEFT(node) (NULL!=(node)?(node)->left:NULL) #define TR_TREE_PARENT(node) (NULL!=(node)?(node)->parent:NULL) +/* + * Find data in a tree. + * Attention: This will change node, so normally you need to copy + * it before using this macro. + * Also be aware that found needs to be a valid lvalue and an integer. + */ +#define TR_TREE_FIND(node, search, found, comp) \ + (found) = -1; \ + while((node) && ((node)->left || (node)->right)) { \ + (found) = (comp)((node)->data, (search)); \ + if (0 != (found)) { \ + if (0 < (found)) { \ + (node) = (node)->left; \ + } else { \ + (node) = (node)->right; \ + } \ + } else { \ + break; \ + } \ + } + #define TR_TREE_CHILD(node) \ (NULL==TR_TREE_RIGHT((node))?TR_TREE_LEFT((node)):TR_TREE_RIGHT((node))) diff --git a/src/tree/delete.c b/src/tree/delete.c index 7c1ec0e..56628a0 100644 --- a/src/tree/delete.c +++ b/src/tree/delete.c @@ -28,35 +28,16 @@ TR_treeDelete(TR_Tree * this, const void * search, TR_TreeComp comp) { TR_Tree node = *this; TR_Tree del_node; + int found; void * data; - /* - * first search for it and if its found return the data - * and we are done... - */ - while (NULL != node) { - int comparison = comp(node->data, search); - - if (0 < comparison) { - node = TR_TREE_LEFT(node); - continue; - } - - if (0 > comparison) { - node = TR_TREE_RIGHT(node); - continue; - } - - if (0 == comparison) { - break; - } - } + TR_TREE_FIND(node, search, found, comp); /* * nothing was found...return NULL to indicate this. */ - if (NULL == node) { + if (found != 0) { return NULL; } diff --git a/src/tree/find.c b/src/tree/find.c index 1cb4e64..fbe7b7c 100644 --- a/src/tree/find.c +++ b/src/tree/find.c @@ -25,25 +25,12 @@ void * TR_treeFind(TR_Tree this, const void * search, TR_TreeComp comp) { - while (NULL != this) { - int comparison = comp(this->data, search); + TR_Tree node = this; + int found; - if (0 < comparison) { - this = TR_TREE_LEFT(this); - continue; - } + TR_TREE_FIND(node, search, found, comp); - if (0 > comparison) { - this = TR_TREE_RIGHT(this); - continue; - } - - if (0 == comparison) { - break; - } - } - - return NULL != this ? this->data : NULL; + return found == 0 ? node->data : NULL; } // vim: set ts=4 sw=4: diff --git a/src/tree/insert.c b/src/tree/insert.c index 00a263e..1ad85a7 100644 --- a/src/tree/insert.c +++ b/src/tree/insert.c @@ -28,6 +28,9 @@ TR_treeInsert(TR_Tree * this, const void * search, TR_TreeComp comp) { TR_Tree node = *this; TR_Tree new_node = NULL; + int found; + + TR_TREE_FIND(node, search, found, comp); /* * 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) */ *this = node = new_node = TR_new(TR_Tree, search); } else { - /* - * first search for it and if its found return the data - * and we are done... - */ - while (NULL != node) { - int comparison = comp(node->data, search); - - if (0 < comparison) { - if (NULL != TR_TREE_LEFT(node)) { - node = TR_TREE_LEFT(node); - continue; - } else { - node->left = TR_new(TR_Tree, search); - node->left->parent = node; - node = new_node = node->left; - break; - } - } - - if (0 > comparison) { - if (NULL != TR_TREE_RIGHT(node)) { - node = TR_TREE_RIGHT(node); - continue; - } else { - node->right = TR_new(TR_Tree, search); - node->right->parent = node; - node = new_node = node->right; - break; - } - } - - if (0 == comparison) { - // as this is insert and not find this will overwrite an existing value, - // but return the previos one so that it can be freed if neccessary. - void * data = node->data; - node->data = (void *)search; - return data; + if (found == 0) { + // we found an element + // as this is insert and not find this will overwrite an existing + // value, but return the previous one so that it can be freed if + // neccessary. + void * data = node->data; + node->data = (void *)search; + return data; + } else { + // not found + if (0 < found) { + node->left = TR_new(TR_Tree, search); + node->left->parent = node; + node = new_node = node->left; + } else { + node->right = TR_new(TR_Tree, search); + node->right->parent = node; + node = new_node = node->right; } } } @@ -114,13 +98,13 @@ TR_treeInsert(TR_Tree * this, const void * search, TR_TreeComp comp) && node->parent == node->parent->parent->left) { TR_TREE_ROTATE(left, this, node->parent); - node = TR_TREE_LEFT(node); + node = node->left; } else if (node == node->parent->left && node->parent == node->parent->parent->right) { TR_TREE_ROTATE(right, this, node->parent); - node = TR_TREE_RIGHT(node); + node = node->right; } diff --git a/trdata.h b/trdata.h index d8978cf..ae6b4fd 100644 --- a/trdata.h +++ b/trdata.h @@ -11,13 +11,13 @@ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the `memset' function. */ -/* #undef HAVE_MEMSET */ +#define HAVE_MEMSET 1 /* Define to 1 if you have the header file. */ #define HAVE_STDARG_H 1 /* Define to 1 if stdbool.h conforms to C99. */ -/* #undef HAVE_STDBOOL_H */ +#define HAVE_STDBOOL_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1