diff --git a/include/Makefile.am b/include/Makefile.am index 04f2508..e7b410d 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -3,6 +3,7 @@ nobase_include_HEADERS = trbase.h \ tr/commons.h \ tr/interface.h \ tr/memory.h \ + tr/tree_macros.h \ tr/interface/class.h \ tr/interface/indexable.h \ tr/interface/observer.h \ diff --git a/include/tr/tree_macros.h b/include/tr/tree_macros.h new file mode 100644 index 0000000..c114b4f --- /dev/null +++ b/include/tr/tree_macros.h @@ -0,0 +1,130 @@ +/** + * \file + * + * \author Georg Hopp + * + * \copyright + * Copyright © 2012 Georg Hopp + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __TR_TREE_MACROS_H__ +#define __TR_TREE_MACROS_H__ + +#include "trbase.h" + +#define TR_TREE_RIGHT(node) (NULL!=(node)?(node)->right:NULL) +#define TR_TREE_LEFT(node) (NULL!=(node)?(node)->left:NULL) +#define TR_TREE_PARENT(node) (NULL!=(node)?(node)->parent:NULL) + +#define TR_TREE_CHILD(node) \ + (NULL==TR_TREE_RIGHT((node))?TR_TREE_LEFT((node)):TR_TREE_RIGHT((node))) + +#define TR_TREE_SIBLING(node) \ + (NULL!=TR_TREE_PARENT((node))? \ + ((node)==TR_TREE_PARENT((node))->left? \ + TR_TREE_PARENT((node))->right: \ + TR_TREE_PARENT((node))->left): \ + NULL) + +#define TR_TREE_GRANDPARENT(node) (TR_TREE_PARENT((node))->parent) + +#define TR_TREE_UNCLE(node) \ + ((node)->parent == (node)->parent->parent->left? \ + (node)->parent->parent->right: \ + (node)->parent->parent->left) + +#define TR_TREE_REPLACE_NODE(root, node1, node2) \ + if (NULL != (node1)->parent) { \ + if ((node1) == (node1)->parent->left) { \ + (node1)->parent->left = (node2); \ + } else { \ + (node1)->parent->right = (node2); \ + } \ + } else { \ + *(root) = (node2); \ + } \ + if (NULL != (node2)) { \ + (node2)->parent = (node1)->parent; \ + } + +#define TR_TREE_ROT_RCLD_right(node) ((node)->left) +#define TR_TREE_ROT_RCLD_left(node) ((node)->right) + +#define TR_TREE_ROTATE(lr, root, node) \ + if (NULL != (node)) { \ + void * stPar = node->parent; \ + void * relCld = TR_TREE_ROT_RCLD_##lr(node); \ + void * relCCld = TR_TREE_ROT_RCLD_##lr(node)->lr; \ + void * nLeft_p = &TR_TREE_ROT_RCLD_##lr(node); \ + if (NULL != relCCld) { \ + TR_TREE_ROT_RCLD_##lr(node)->lr->parent = node; \ + } \ + TR_TREE_ROT_RCLD_##lr(node)->lr = node; \ + if (NULL != node->parent) { \ + if (node->parent->left == node) { \ + node->parent->left = relCld; \ + } else { \ + node->parent->right = relCld; \ + } \ + } else { \ + *(root) = relCld; \ + } \ + node->parent = relCld; \ + TR_TREE_ROT_RCLD_##lr(node)->parent = stPar; \ + *(void**)nLeft_p = relCCld; \ + } + +typedef enum {rbBlack=1, rbRed=2} TR_rbColor; + +#define TR_TREE_NODE_BLACK(node) (NULL == (node) || rbBlack == (node)->color) +#define TR_TREE_NODE_RED(node) (NULL == (node) || rbRed == (node)->color) +#define TR_TREE_NODE_STRICT_BLACK(node) (NULL != (node) && rbBlack == (node)->color) +#define TR_TREE_NODE_STRICT_RED(node) (NULL != (node) && rbRed == (node)->color) + +#define TR_TREE_INORDER_SUCC(node, succ) \ + succ = (node)->right; \ + while (NULL != succ->left) { \ + succ = succ->left; \ + } +/* + * 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; \ + if ((node)) { \ + while(1) { \ + (found) = (comp)((node)->data, (search)); \ + if (0 != (found)) { \ + if (! ((node)->left || (node)->right)) { \ + break; \ + } \ + if (0 < (found)) { \ + (node) = (node)->left; \ + } else { \ + (node) = (node)->right; \ + } \ + } else { \ + break; \ + } \ + } \ + } + +#endif // __TR_TREE_MACROS_H__ + +// vim: set ts=4 sw=4: diff --git a/src/memory.c b/src/memory.c index e7257d7..a2fc185 100644 --- a/src/memory.c +++ b/src/memory.c @@ -98,6 +98,30 @@ newElement(size_t size) return element; } +static +int +_memSegmentFindCompare(const void * a, const void * b) +{ + struct memSegment * _a = (struct memSegment *)a; + size_t _b = *(size_t *)b; + + /* + * find the smallest bigger or equal size segment + */ + return _a->size < _b ? -1 + : _a->size > _b && _a->left && _a->left->size >= _b ? 1 : 0; +} + +static +int +_memSegmentCompare(const void * a, const void * b) +{ + size_t _a = ((struct memSegment *)a)->size; + size_t _b = ((struct memSegment *)b)->size; + + return _a < _b ? -1 : _a > _b ? 1 : 0; +} + /** * find element in tree */ @@ -105,23 +129,11 @@ static struct memSegment * findElement(struct memSegment * tree, size_t size) { - struct memSegment * fitting = NULL; - - while (NULL != tree) { - if (tree->size == size) { - fitting = tree; - break; - } + int found; - if (size > tree->size) { - tree = tree->right; - } else { - fitting = tree; - tree = tree->left; - } - } + TR_TREE_FIND(tree, &size, found, _memSegmentFindCompare); - return fitting; + return found == 0 ? tree : NULL; } /** @@ -135,6 +147,7 @@ insertElement(struct memSegment ** tree, struct memSegment * element) struct memSegment * new_node = NULL; struct memSegment * u; struct memSegment * g; + int found; element->next = NULL; element->last = NULL; @@ -144,42 +157,35 @@ insertElement(struct memSegment ** tree, struct memSegment * element) element->left = NULL; element->right = NULL; + TR_TREE_FIND(node, element, found, _memSegmentCompare); + // if tree is empty it's simple... :) if (NULL == node) { *tree = node = new_node = element; - } else { - // normal binary tree add.... - while (NULL != node) { - if (element->size < node->size) { - if (NULL == node->left) { - node->left = element; - node->left->parent = node; - new_node = node = node->left; - break; - } else { - node = node->left; - } - } else if (element->size > node->size) { - if (NULL == node->right) { - node->right = element; - node->right->parent = node; - new_node = node = node->right; - break; - } else { - node = node->right; - } - } else { - if (NULL == node->next) { - node->next = element; - node->last = element; - } else { - node->last->next = element; - node->last = element; - } - return node; - } - } - } + } else { + // normal binary tree add.... + if (found == 0) { + if (NULL == node->next) { + node->next = element; + node->last = element; + } else { + node->last->next = element; + node->last = element; + } + return node; + } else { + if (0 < found) { + node->left = element; + node->left->parent = node; + new_node = node = node->left; + } else { + node->right = element; + node->right->parent = node; + new_node = node = node->right; + + } + } + } if (NULL != new_node) { /* @@ -250,50 +256,43 @@ deleteElement(struct memSegment ** tree, struct memSegment * element) struct memSegment * del_node; struct memSegment * child; struct memSegment * s; + int found; // find the relevant node and it's parent - while (NULL != node) { - - if (element->size < node->size) { - node = node->left; - } else if (element->size > node->size) { - node = node->right; - } else { - if (NULL != node->next) { - if (NULL != node->parent) { - if (node == node->parent->left) { - node->parent->left = node->next; - } else { - node->parent->right = node->next; - } - } else { - *tree = node->next; - } + TR_TREE_FIND(node, element, found, _memSegmentCompare); - if (NULL != node->left) { - node->left->parent = node->next; - } + //while (node) { + if (found != 0) { + return NULL; + } else { + if (NULL != node->next) { + if (NULL != node->parent) { + if (node == node->parent->left) { + node->parent->left = node->next; + } else { + node->parent->right = node->next; + } + } else { + *tree = node->next; + } - if (NULL != node->right) { - node->right->parent = node->next; - } - - node->next->last = node->last; - node->next->color = node->color; - node->next->parent = node->parent; - node->next->left = node->left; - node->next->right = node->right; - - return node; - } - break; - } - } + if (NULL != node->left) { + node->left->parent = node->next; + } - // element not found - if (NULL == node) { - return node; - } + if (NULL != node->right) { + node->right->parent = node->next; + } + + node->next->last = node->last; + node->next->color = node->color; + node->next->parent = node->parent; + node->next->left = node->left; + node->next->right = node->right; + + return node; + } + } del_node = node;