Browse Source

started some optimizations, but with not much effect for now

1.0.0
Georg Hopp 12 years ago
parent
commit
895e789181
  1. 131
      include/tr/tree.h
  2. 8
      src/tree/Makefile.am
  3. 120
      src/tree/delete.c
  4. 37
      src/tree/inOrderSuccessor.c
  5. 44
      src/tree/insert.c
  6. 51
      src/tree/rotateLeft.c
  7. 51
      src/tree/rotateRight.c

131
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;

8
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/

120
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);
}
}

37
src/tree/inOrderSuccessor.c

@ -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 <http://www.gnu.org/licenses/>.
*/
#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:

44
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;

51
src/tree/rotateLeft.c

@ -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 <http://www.gnu.org/licenses/>.
*/
#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:

51
src/tree/rotateRight.c

@ -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 <http://www.gnu.org/licenses/>.
*/
#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:
Loading…
Cancel
Save