From 895e789181141deb58ddec2dd56956869e7c716c Mon Sep 17 00:00:00 2001 From: Georg Hopp Date: Tue, 17 Jun 2014 16:29:18 +0100 Subject: [PATCH] started some optimizations, but with not much effect for now --- include/tr/tree.h | 131 ++++++++++++++++-------------------- src/tree/Makefile.am | 8 ++- src/tree/delete.c | 120 +++++++++++++-------------------- src/tree/inOrderSuccessor.c | 37 ---------- src/tree/insert.c | 44 +++++------- src/tree/rotateLeft.c | 51 -------------- src/tree/rotateRight.c | 51 -------------- 7 files changed, 129 insertions(+), 313 deletions(-) delete mode 100644 src/tree/inOrderSuccessor.c delete mode 100644 src/tree/rotateLeft.c delete mode 100644 src/tree/rotateRight.c diff --git a/include/tr/tree.h b/include/tr/tree.h index e491b1a..cc6ea06 100644 --- a/include/tr/tree.h +++ b/include/tr/tree.h @@ -25,19 +25,13 @@ #include "trbase.h" -#define TR_TREE_RIGHT(node) (NULL!=(node)?(node)->right:NULL) +#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_RIGHT_LEFT(node) \ - (NULL!=TR_TREE_RIGHT((node))?TR_TREE_LEFT(TR_TREE_RIGHT((node))):NULL) - -#define TR_TREE_LEFT_RIGHT(node) \ - (NULL!=TR_TREE_LEFT((node))?TR_TREE_RIGHT(TR_TREE_LEFT((node))):NULL) - #define TR_TREE_SIBLING(node) \ (NULL!=TR_TREE_PARENT((node))? \ ((node)==TR_TREE_PARENT((node))->left? \ @@ -45,74 +39,67 @@ TR_TREE_PARENT((node))->left): \ NULL) -#define TR_TREE_GRANDPARENT(node) \ - (NULL!=TR_TREE_PARENT((node))?TR_TREE_PARENT((node))->parent:NULL) - -#define TR_TREE_UNCLE(node) \ - (NULL!=TR_TREE_GRANDPARENT((node))? \ - (TR_TREE_PARENT((node))==TR_TREE_GRANDPARENT((node))->left? \ - TR_TREE_GRANDPARENT((node))->right: \ - TR_TREE_GRANDPARENT((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_RELCHILD_right(node) ((node)->left) +#define TR_TREE_ROT_RELCHILD_CHILD_right (relChild->right) +#define TR_TREE_ROT_RELCHILD_left(node) ((node)->right) +#define TR_TREE_ROT_RELCHILD_CHILD_left (relChild->left) + +#define TR_TREE_ROTATE(lr, _this, node) \ + if (NULL != (node)) { \ + TR_Tree _node = (node); \ + TR_Tree relChild = TR_TREE_ROT_RELCHILD_##lr(_node); \ + TR_Tree relChildLvl2 = TR_TREE_ROT_RELCHILD_##lr(_node)->lr; \ + relChild->lr = _node; \ + relChild->parent = _node->parent; \ + TR_TREE_ROT_RELCHILD_##lr(_node) = relChildLvl2; \ + if (NULL != relChildLvl2) { \ + relChildLvl2->parent = _node; \ + } \ + if (NULL != _node->parent) { \ + if (_node->parent->left == _node) { \ + _node->parent->left = relChild; \ + } else { \ + _node->parent->right = relChild; \ + } \ + } else { \ + *(_this) = relChild; \ + } \ + _node->parent = relChild; \ + } -#define TR_TREE_ROTATE_LEFT(root, node) \ - do { \ - if (NULL != TR_TREE_RIGHT_LEFT((node))) { \ - TR_TREE_RIGHT_LEFT((node))->parent = (node); \ - } \ - TR_TREE_RIGHT((node))->left = (node); \ - if (NULL != TR_TREE_PARENT((node))) { \ - if (TR_TREE_PARENT((node))->left==(node)) { \ - TR_TREE_PARENT((node))->left = (node)->right; \ - } else { \ - TR_TREE_PARENT((node))->right = (node)->right; \ - } \ - } else { \ - *(root) = (node)->right; \ - } \ - (node)->right = TR_TREE_RIGHT_LEFT((node)); \ - (node)->parent = (node)->right; \ - TR_TREE_RIGHT((node))->parent = (node)->parent; \ - } while(0) - -#define TR_TREE_ROTATE_RIGHT(root, node) \ - do { \ - if (NULL != TR_TREE_LEFT_RIGHT((node))) { \ - TR_TREE_LEFT_RIGHT((node))->parent = (node); \ - } \ - TR_TREE_LEFT((node))->right = (node); \ - if (NULL != TR_TREE_PARENT((node))) { \ - if (TR_TREE_PARENT((node))->left==(node)) { \ - TR_TREE_PARENT((node))->left = (node)->left; \ - } else { \ - TR_TREE_PARENT((node))->right = (node)->left; \ - } \ - } else { \ - *(root) = (node)->left; \ - } \ - TR_TREE_LEFT((node))->parent = (node)->parent; \ - (node)->left = TR_TREE_LEFT_RIGHT((node)); \ - (node)->parent = (node)->right; \ - } while(0) - -#define TR_TREE_REPLACE_NODE(root, node1, node2) \ - do { \ - if (NULL != TR_TREE_PARENT((node1))) { \ - if ((node1) == TR_TREE_PARENT((node1))->left) { \ - TR_TREE_PARENT((node1))->left = (node2); \ - } else { \ - TR_TREE_PARENT((node1))->right = (node2); \ - } \ - } else { \ - *(root) = (node2); \ - } \ - if (NULL != (node2)) { \ - (node2)->parent = (node1)->parent; \ - } \ - } while(0) +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) -typedef enum {rbBlack=1, rbRed=2} TR_rbColor; +#define TR_TREE_INORDER_SUCC(node, succ) \ + succ = TR_TREE_RIGHT((node)); \ + while (NULL != succ->left) { \ + succ = succ->left; \ + } TR_CLASS(TR_Tree) { void * data; diff --git a/src/tree/Makefile.am b/src/tree/Makefile.am index 49c09b7..7707edc 100644 --- a/src/tree/Makefile.am +++ b/src/tree/Makefile.am @@ -1,8 +1,12 @@ ACLOCAL_AMFLAGS = -I m4 AUTOMAKE_OPTIONS = subdir-objects -TREE = tree.c find.c insert.c inOrderSuccessor.c delete.c walk.c \ - rotateLeft.c rotateRight.c destroy.c +TREE = tree.c \ + find.c \ + insert.c \ + inOrderSuccessor.c \ + delete.c walk.c \ + destroy.c AM_CFLAGS += -I../../include/ diff --git a/src/tree/delete.c b/src/tree/delete.c index fe16747..daccfa8 100644 --- a/src/tree/delete.c +++ b/src/tree/delete.c @@ -23,10 +23,6 @@ #include "trbase.h" #include "tr/tree.h" -TR_Tree TR_inOrderSuccessor(TR_Tree); -void TR_treeRotateLeft(TR_Tree *, TR_Tree); -void TR_treeRotateRight(TR_Tree *, TR_Tree); - void * TR_treeDelete(TR_Tree * this, const void * search, TR_TreeComp comp) { @@ -79,7 +75,9 @@ TR_treeDelete(TR_Tree * this, const void * search, TR_TreeComp comp) * out inOrderSuccessor and remove the inOrderSuccessor. */ if (NULL != TR_TREE_LEFT(node) && NULL != TR_TREE_RIGHT(node)) { - TR_Tree successor = TR_inOrderSuccessor(node); + TR_Tree successor; + + TR_TREE_INORDER_SUCC(node, successor); node->data = successor->data; node = successor; @@ -126,113 +124,91 @@ TR_treeDelete(TR_Tree * this, const void * search, TR_TreeComp comp) * to be honest I don't know now.) */ while(1) { + TR_Tree sibling; + // case 1 if (NULL == TR_TREE_PARENT(node)) { break; } - // case 2 - if (NULL != TR_TREE_SIBLING(node) - && rbRed == TR_TREE_SIBLING(node)->color) { - - TR_TREE_PARENT(node)->color = rbRed; - TR_TREE_SIBLING(node)->color = rbBlack; - - if (NULL != TR_TREE_PARENT(node)->right && - node != TR_TREE_PARENT(node)->right) { - - //TREE_ROTATE_LEFT(this, TREE_PARENT(node)); - TR_treeRotateLeft(this, TR_TREE_PARENT(node)); + sibling = TR_TREE_SIBLING(node); + if (NULL != sibling && rbRed == sibling->color) { + // case 2 + node->parent->color = rbRed; + sibling->color = rbBlack; + if (NULL != node->parent->right && node != node->parent->right) { + TR_TREE_ROTATE(left, this, node->parent); } else { - - //TREE_ROTATE_RIGHT(this, TREE_PARENT(node)); - TR_treeRotateRight(this, TR_TREE_PARENT(node)); - + TR_TREE_ROTATE(right, this, node->parent); } - } - - // case 3 / 4 - if (NULL == TR_TREE_SIBLING(node) - || (rbBlack == TR_TREE_SIBLING(node)->color - && (NULL == TR_TREE_SIBLING(node)->left - || rbBlack == TR_TREE_SIBLING(node)->left->color) - && (NULL == TR_TREE_SIBLING(node)->right - || rbBlack == TR_TREE_SIBLING(node)->right->color))) { - - if (NULL != TR_TREE_SIBLING(node)) { - TR_TREE_SIBLING(node)->color = rbRed; + } else { + // case 3/4 + if (NULL != sibling + && TR_TREE_NODE_BLACK(sibling->left) + && TR_TREE_NODE_BLACK(sibling->right)) { + sibling->color = rbRed; } - /* * this is the point where during the balancing our tree * node can be finally deleted. */ - if (rbBlack == TR_TREE_PARENT(node)->color) { + if (rbBlack == node->parent->color) { // case 3 - TR_Tree parent = node->parent; - node = parent; + node = node->parent; continue; } else { // case 4 - TR_TREE_PARENT(node)->color = rbBlack; + node->parent->color = rbBlack; break; } } // case 5 - if (NULL != TR_TREE_SIBLING(node) - && rbBlack == TR_TREE_SIBLING(node)->color) { + if (NULL != sibling && rbBlack == sibling->color) { - if (node == TR_TREE_PARENT(node)->left - && (NULL == TR_TREE_SIBLING(node)->right - || rbBlack == TR_TREE_SIBLING(node)->right->color) - && (NULL != TR_TREE_SIBLING(node)->left - && rbRed == TR_TREE_SIBLING(node)->left->color)) { + if (node == node->parent->left + && TR_TREE_NODE_BLACK(sibling->right) + && TR_TREE_NODE_STRICT_RED(sibling->left)) { - TR_TREE_SIBLING(node)->color = rbRed; - TR_TREE_SIBLING(node)->left->color = rbBlack; + sibling->color = rbRed; + sibling->left->color = rbBlack; - //TREE_ROTATE_RIGHT(this, TREE_SIBLING(node)); - TR_treeRotateRight(this, TR_TREE_SIBLING(node)); + TR_TREE_ROTATE(right, this, sibling); - } else if (node == TR_TREE_PARENT(node)->right - && (NULL == TR_TREE_SIBLING(node)->left - || rbBlack == TR_TREE_SIBLING(node)->left->color) - && (NULL != TR_TREE_SIBLING(node)->right - && rbRed == TR_TREE_SIBLING(node)->right->color)) { + } else if (node == node->parent->right + && TR_TREE_NODE_BLACK(sibling->left) + && TR_TREE_NODE_STRICT_RED(sibling->right)) { - TR_TREE_SIBLING(node)->color = rbRed; - TR_TREE_SIBLING(node)->right->color = rbBlack; + sibling->color = rbRed; + sibling->right->color = rbBlack; - //TREE_ROTATE_LEFT(this, TREE_SIBLING(node)); - TR_treeRotateLeft(this, TR_TREE_SIBLING(node)); + TR_TREE_ROTATE(left, this, sibling); } } // case 6 - if (NULL != TR_TREE_SIBLING(node)) { - TR_TREE_SIBLING(node)->color = TR_TREE_PARENT(node)->color; + // do we need to reinitialize sibling here? + if (NULL != sibling) { + sibling->color = node->parent->color; } - if (NULL != node && NULL != TR_TREE_PARENT(node)) { - TR_TREE_PARENT(node)->color = rbBlack; + if (NULL != node && NULL != node->parent) { + node->parent->color = rbBlack; - if (NULL != TR_TREE_PARENT(node)->right - && node != TR_TREE_PARENT(node)->right) { + if (NULL != node->parent->right + && node != node->parent->right) { - if (NULL != TR_TREE_SIBLING(node)->right) { - TR_TREE_SIBLING(node)->right->color = rbBlack; + if (NULL != sibling->right) { + sibling->right->color = rbBlack; } - //TREE_ROTATE_LEFT(this, TREE_PARENT(node)); - TR_treeRotateLeft(this, TR_TREE_PARENT(node)); + TR_TREE_ROTATE(left, this, node->parent); } else { - if (NULL != TR_TREE_SIBLING(node)->left) { - TR_TREE_SIBLING(node)->left->color = rbBlack; + if (NULL != sibling->left) { + sibling->left->color = rbBlack; } - //TREE_ROTATE_RIGHT(this, TREE_PARENT(node)); - TR_treeRotateRight(this, TR_TREE_PARENT(node)); + TR_TREE_ROTATE(right, this, node->parent); } } diff --git a/src/tree/inOrderSuccessor.c b/src/tree/inOrderSuccessor.c deleted file mode 100644 index 9adb58a..0000000 --- a/src/tree/inOrderSuccessor.c +++ /dev/null @@ -1,37 +0,0 @@ -/** - * \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 . - */ - -#include "tr/tree.h" - -TR_Tree -TR_inOrderSuccessor(TR_Tree this) -{ - this = TR_TREE_RIGHT(this); - - while (NULL != TR_TREE_LEFT(this)) { - this = TR_TREE_LEFT(this); - } - - return this; -} - -// vim: set ts=4 sw=4: diff --git a/src/tree/insert.c b/src/tree/insert.c index 70e40e0..b3ef509 100644 --- a/src/tree/insert.c +++ b/src/tree/insert.c @@ -23,9 +23,6 @@ #include "trbase.h" #include "tr/tree.h" -void TR_treeRotateLeft(TR_Tree *, TR_Tree); -void TR_treeRotateRight(TR_Tree *, TR_Tree); - void * TR_treeInsert(TR_Tree * this, const void * search, TR_TreeComp comp) { @@ -47,16 +44,17 @@ TR_treeInsert(TR_Tree * this, const void * search, TR_TreeComp comp) * first search for it and if its found return the data * and we are done... */ - int comparison; - while (NULL != node) { - comparison = comp(node->data, search); + 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; } } @@ -66,26 +64,20 @@ TR_treeInsert(TR_Tree * this, const void * search, TR_TreeComp comp) 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) { - return node->data; + // 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; } - } - - /* - * as we have not found it now add a new element. - */ - if (0 < comparison) { - node->left = TR_new(TR_Tree, search); - TR_TREE_LEFT(node)->parent = node; - node = new_node = TR_TREE_LEFT(node); - } else { - node->right = TR_new(TR_Tree, search); - TR_TREE_RIGHT(node)->parent = node; - node = new_node = TR_TREE_RIGHT(node); } } @@ -119,15 +111,13 @@ TR_treeInsert(TR_Tree * this, const void * search, TR_TreeComp comp) if (node == TR_TREE_PARENT(node)->right && TR_TREE_PARENT(node) == TR_TREE_GRANDPARENT(node)->left) { - //TREE_ROTATE_LEFT(this, TREE_PARENT(node)); - TR_treeRotateLeft(this, TR_TREE_PARENT(node)); + TR_TREE_ROTATE(left, this, TR_TREE_PARENT(node)); node = TR_TREE_LEFT(node); } else if (node == TR_TREE_PARENT(node)->left && TR_TREE_PARENT(node) == TR_TREE_GRANDPARENT(node)->right) { - //TREE_ROTATE_RIGHT(this, TREE_PARENT(node)); - TR_treeRotateRight(this, TR_TREE_PARENT(node)); + TR_TREE_ROTATE(right, this, TR_TREE_PARENT(node)); node = TR_TREE_RIGHT(node); } @@ -137,11 +127,9 @@ TR_treeInsert(TR_Tree * this, const void * search, TR_TreeComp comp) TR_TREE_GRANDPARENT(node)->color = rbRed; if (node == TR_TREE_PARENT(node)->left) { - //TREE_ROTATE_RIGHT(this, TREE_GRANDPARENT(node)); - TR_treeRotateRight(this, TR_TREE_GRANDPARENT(node)); + TR_TREE_ROTATE(right, this, TR_TREE_GRANDPARENT(node)); } else { - //TREE_ROTATE_LEFT(this, TREE_GRANDPARENT(node)); - TR_treeRotateLeft(this, TR_TREE_GRANDPARENT(node)); + TR_TREE_ROTATE(left, this, TR_TREE_GRANDPARENT(node)); } break; diff --git a/src/tree/rotateLeft.c b/src/tree/rotateLeft.c deleted file mode 100644 index 0f39025..0000000 --- a/src/tree/rotateLeft.c +++ /dev/null @@ -1,51 +0,0 @@ -/** - * \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 . - */ - -#include "tr/tree.h" - -void -TR_treeRotateLeft(TR_Tree * this, TR_Tree node) -{ - TR_Tree rightChild = TR_TREE_RIGHT(node); - TR_Tree rcLeftSub = TR_TREE_RIGHT_LEFT(node); - - rightChild->left = node; - rightChild->parent = TR_TREE_PARENT(node); - node->right = rcLeftSub; - if (NULL != rcLeftSub) { - rcLeftSub->parent = node; - } - - if (NULL != TR_TREE_PARENT(node)) { - if (TR_TREE_PARENT(node)->left == node) { - TR_TREE_PARENT(node)->left = rightChild; - } else { - TR_TREE_PARENT(node)->right = rightChild; - } - } else { - *this = rightChild; - } - - node->parent = rightChild; -} - -// vim: set ts=4 sw=4: diff --git a/src/tree/rotateRight.c b/src/tree/rotateRight.c deleted file mode 100644 index 2c41f22..0000000 --- a/src/tree/rotateRight.c +++ /dev/null @@ -1,51 +0,0 @@ -/** - * \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 . - */ - -#include "tr/tree.h" - -void -TR_treeRotateRight(TR_Tree * this, TR_Tree node) -{ - TR_Tree leftChild = TR_TREE_LEFT(node); - TR_Tree lcRightSub = TR_TREE_LEFT_RIGHT(node); - - leftChild->right = node; - leftChild->parent = TR_TREE_PARENT(node); - node->left = lcRightSub; - if (NULL != lcRightSub) { - lcRightSub->parent = node; - } - - if (NULL != TR_TREE_PARENT(node)) { - if (TR_TREE_PARENT(node)->left == node) { - TR_TREE_PARENT(node)->left = leftChild; - } else { - TR_TREE_PARENT(node)->right = leftChild; - } - } else { - *this = leftChild; - } - - node->parent = leftChild; -} - -// vim: set ts=4 sw=4: