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: