Browse Source

use now my own tree implementation as base for my hashes....sadly this thing is leaking memory again...on the other hand I workarounded the problem of a sometimes occuring infinite loop within connect.

release0.1.5
Georg Hopp 12 years ago
parent
commit
c8dc541c48
  1. 1
      configure.ac
  2. 3
      include/hash/hash.h
  3. 138
      include/tree.h
  4. 5
      src/Makefile.am
  5. 7
      src/asset/asset.c
  6. 19
      src/asset/pool.c
  7. 21
      src/hash/add.c
  8. 58
      src/hash/delete.c
  9. 8
      src/hash/each.c
  10. 19
      src/hash/get.c
  11. 9
      src/hash/hash.c
  12. 4
      src/rbtree.c
  13. 144
      src/rbtree2.c
  14. 6
      src/server/run.c
  15. 9
      src/tree/Makefile.am
  16. 248
      src/tree/delete.c
  17. 84
      src/tree/destroy.c
  18. 49
      src/tree/find.c
  19. 37
      src/tree/inOrderSuccessor.c
  20. 152
      src/tree/insert.c
  21. 51
      src/tree/rotateLeft.c
  22. 51
      src/tree/rotateRight.c
  23. 54
      src/tree/tree.c
  24. 59
      src/tree/walk.c
  25. 8
      src/utils/memory.c

1
configure.ac

@ -63,5 +63,6 @@ AC_CONFIG_FILES([Makefile
src/session/Makefile
src/socket/Makefile
src/stream/Makefile
src/tree/Makefile
tests/Makefile])
AC_OUTPUT

3
include/hash/hash.h

@ -26,10 +26,11 @@
#include <sys/types.h>
#include "class.h"
#include "tree.h"
CLASS(Hash) {
void * root;
Tree root;
};
void * hashAdd(Hash, void *);

138
include/tree.h

@ -0,0 +1,138 @@
/**
* \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/>.
*/
#ifndef __TREE_H__
#define __TREE_H__
#include "class.h"
#define TREE_RIGHT(node) (NULL!=(node)?(node)->right:NULL)
#define TREE_LEFT(node) (NULL!=(node)?(node)->left:NULL)
#define TREE_PARENT(node) (NULL!=(node)?(node)->parent:NULL)
#define TREE_CHILD(node) \
(NULL==TREE_RIGHT((node))?TREE_LEFT((node)):TREE_RIGHT((node)))
#define TREE_RIGHT_LEFT(node) \
(NULL!=TREE_RIGHT((node))?TREE_LEFT(TREE_RIGHT((node))):NULL)
#define TREE_LEFT_RIGHT(node) \
(NULL!=TREE_LEFT((node))?TREE_RIGHT(TREE_LEFT((node))):NULL)
#define TREE_SIBLING(node) \
(NULL!=TREE_PARENT((node))? \
((node)==TREE_PARENT((node))->left? \
TREE_PARENT((node))->right: \
TREE_PARENT((node))->left): \
NULL)
#define TREE_GRANDPARENT(node) \
(NULL!=TREE_PARENT((node))?TREE_PARENT((node))->parent:NULL)
#define TREE_UNCLE(node) \
(NULL!=TREE_GRANDPARENT((node))? \
(TREE_PARENT((node))==TREE_GRANDPARENT((node))->left? \
TREE_GRANDPARENT((node))->right: \
TREE_GRANDPARENT((node))->left): \
NULL)
#define TREE_ROTATE_LEFT(root, node) \
do { \
if (NULL != TREE_RIGHT_LEFT((node))) { \
TREE_RIGHT_LEFT((node))->parent = (node); \
} \
TREE_RIGHT((node))->left = (node); \
if (NULL != TREE_PARENT((node))) { \
if (TREE_PARENT((node))->left==(node)) { \
TREE_PARENT((node))->left = (node)->right; \
} else { \
TREE_PARENT((node))->right = (node)->right; \
} \
} else { \
*(root) = (node)->right; \
} \
(node)->right = TREE_RIGHT_LEFT((node)); \
(node)->parent = (node)->right; \
TREE_RIGHT((node))->parent = (node)->parent; \
} while(0)
#define TREE_ROTATE_RIGHT(root, node) \
do { \
if (NULL != TREE_LEFT_RIGHT((node))) { \
TREE_LEFT_RIGHT((node))->parent = (node); \
} \
TREE_LEFT((node))->right = (node); \
if (NULL != TREE_PARENT((node))) { \
if (TREE_PARENT((node))->left==(node)) { \
TREE_PARENT((node))->left = (node)->left; \
} else { \
TREE_PARENT((node))->right = (node)->left; \
} \
} else { \
*(root) = (node)->left; \
} \
TREE_LEFT((node))->parent = (node)->parent; \
(node)->left = TREE_LEFT_RIGHT((node)); \
(node)->parent = (node)->right; \
} while(0)
#define TREE_REPLACE_NODE(root, node1, node2) \
do { \
if (NULL != TREE_PARENT((node1))) { \
if ((node1) == TREE_PARENT((node1))->left) { \
TREE_PARENT((node1))->left = (node2); \
} else { \
TREE_PARENT((node1))->right = (node2); \
} \
} else { \
*(root) = (node2); \
} \
if (NULL != (node2)) { \
(node2)->parent = (node1)->parent; \
} \
} while(0)
enum rbColor {rbBlack=1, rbRed=2};
CLASS(Tree) {
void * data;
enum rbColor color;
Tree parent;
Tree left;
Tree right;
};
typedef int (*TreeComp)(const void *, const void *);
typedef void (*TreeAction)(const void *, const int);
void * treeFind(Tree, const void *, TreeComp);
void * treeInsert(Tree *, const void *, TreeComp);
void * treeDelete(Tree *, const void *, TreeComp);
void treeWalk(Tree, TreeAction);
void treeDestroy(Tree *, TreeAction);
#endif // __TREE_H__
// vim: set ts=4 sw=4:

5
src/Makefile.am

@ -21,7 +21,8 @@ LIBS = ./http/libhttp.a \
./server/libserver.a \
./session/libsession.a \
./socket/libsocket.a \
./stream/libstream.a
./stream/libstream.a \
./tree/libtree.a
AM_CFLAGS = -Wall -I ../include/
@ -33,4 +34,4 @@ taskrambler_LDADD = $(LIBS) -lrt -lssl -lldap
#taskrambler_LDFLAGS = $(COVERAGE_LDFLAGS)
SUBDIRS = asset auth cbuf class hash queue http \
logger server session socket stream
logger server session socket stream tree

7
src/asset/asset.c

@ -20,10 +20,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// for debug
#include <stdio.h>
#include <stdarg.h>
// for mmap
@ -105,9 +101,6 @@ assetCtor(void * _this, va_list * params)
return -1;
}
printf("DEBUG file mapped from %p to %p\n",
this->data, this->data + this->size);
this->ref_count = 1;
return 0;

19
src/asset/pool.c

@ -20,9 +20,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// for debugging
#include <stdio.h>
// for size_t
#include <sys/types.h>
@ -47,8 +44,6 @@ assetPoolGet(const char * path, size_t npath)
{
Asset asset = NULL;
printf("DEBUG: pool get asset --%s--\n", path);
if (NULL == asset_pool) {
asset_pool = new(Hash);
} else {
@ -57,12 +52,9 @@ assetPoolGet(const char * path, size_t npath)
if (NULL == asset) {
asset = new(Asset, path, npath);
printf("DEBUG create asset %p\n", asset);
hashAdd(asset_pool, asset);
} else {
printf("DEBUG found asset %p\n", asset);
asset->ref_count++;
printf("DEBUG increase ref_count to %zu\n", asset->ref_count);
}
return asset;
@ -71,19 +63,20 @@ assetPoolGet(const char * path, size_t npath)
size_t
assetPoolRelease(Asset asset)
{
printf("DEBUG: pool release asset --%s--\n", asset->fname);
if (asset->ref_count > 1) {
asset->ref_count--;
printf("DEBUG decrease ref_count to %zu\n", asset->ref_count);
return asset->ref_count;
}
if (NULL != asset) {
Asset found = (Asset)hashDelete(
asset_pool, asset->fname, asset->nfname);
printf("DEBUG delete %p, parent was %p\n", asset, found);
delete(asset);
if (found == asset) {
delete(found);
} else {
// this should never happen....error log...
}
}
return 0;

21
src/hash/add.c

@ -30,24 +30,35 @@ inline
int
hashAddComp(const void * a, const void * b)
{
return hashableGetHash((void*)b) - hashableGetHash((void*)a);
unsigned long hash_a = hashableGetHash((void*)a);
unsigned long hash_b = hashableGetHash((void*)b);
if (hash_a < hash_b) {
return -1;
}
if (hash_a > hash_b) {
return 1;
}
return 0;
}
void *
hashAdd(Hash this, void * operand)
{
void * found = tsearch(operand, &(this->root), hashAddComp);
void * found = treeInsert(&this->root, operand, hashAddComp);
if (NULL == found) {
return NULL;
}
if (operand != *(void**)found) {
hashableHandleDouble(*(void**)found, operand);
if (operand != found) {
hashableHandleDouble(found, operand);
delete(operand);
}
return *(void**)found;
return found;
}
// vim: set ts=4 sw=4:

58
src/hash/delete.c

@ -20,9 +20,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <search.h>
#include <sys/types.h>
#include "asset.h"
@ -34,59 +31,26 @@ inline
int
hashDeleteComp(const void * a, const void * b)
{
if (_Asset == GET_CLASS(b)) {
Asset data = (Asset)b;
printf("DEBUG: search asset hash: %lu\n",
*(const unsigned long*)a);
printf("DEBUG: found: %lu, key: %s\n",
data->hash, data->fname);
}
unsigned long hash_a = hashableGetHash((void*)a);
return hashableGetHash((void*)b) - *(const unsigned long*)a;
}
void
action(const void *nodep, const VISIT which, const int depth)
{
void * datap = *(void **)nodep;
if (_Asset == GET_CLASS(datap)) {
Asset data = (Asset)datap;
if (hash_a < *(const unsigned long*)b) {
return -1;
}
switch (which) {
case preorder:
break;
case postorder:
printf("DEBUG: %s(%lu) => %p\n", data->fname, data->hash, data);
break;
case endorder:
break;
case leaf:
printf("DEBUG: %s(%lu) => %p\n", data->fname, data->hash, data);
break;
}
if (hash_a > *(const unsigned long*)b) {
return 1;
}
return 0;
}
void *
hashDelete(Hash this, const char * search, size_t nsearch)
{
unsigned long hash = sdbm((const unsigned char *)search, nsearch);
void * found = NULL;
int count = 0;
unsigned long hash = sdbm((const unsigned char *)search, nsearch);
void * found = NULL;
twalk(this->root, action);
while (found == NULL && count < 3) {
found = tdelete(&hash, &(this->root), hashDeleteComp);
if (found == NULL) {
puts("DEBUG: !!!!! NOT FOUND !!!!!!!");
void * found = hashGet(this, search, nsearch);
printf("DEBUG: find results in %p\n", found);
}
count++;
}
puts("===");
twalk(this->root, action);
found = treeDelete(&(this->root), &hash, hashDeleteComp);
return found;
}

8
src/hash/each.c

@ -29,11 +29,9 @@ static void (*cb)(const void*);
static
inline
void
walk(const void * node, const VISIT which, const int depth)
walk(const void * node, const int depth)
{
if (endorder == which || leaf == which) {
cb(*(void**)node);
}
cb(node);
}
void
@ -41,7 +39,7 @@ hashEach(Hash this, void (*callback)(const void*))
{
cb = callback;
twalk(this->root, walk);
treeWalk(this->root, walk);
}
// vim: set ts=4 sw=4:

19
src/hash/get.c

@ -26,6 +26,7 @@
#include <sys/types.h>
#include "hash.h"
#include "tree.h"
#include "utils/hash.h"
static
@ -33,16 +34,26 @@ inline
int
hashGetComp(const void * a, const void * b)
{
return hashableGetHash((void*)b) - *(const unsigned long*)a;
unsigned long hash_a = hashableGetHash((void*)a);
if (hash_a < *(const unsigned long*)b) {
return -1;
}
if (hash_a > *(const unsigned long*)b) {
return 1;
}
return 0;
}
void *
hashGet(Hash this, const char * search, size_t nsearch)
{
unsigned long hash = sdbm((const unsigned char *)search, nsearch);
void ** found = tfind(&hash, &(this->root), hashGetComp);
unsigned long hash = sdbm((const unsigned char *)search, nsearch);
void * found = treeFind(this->root, &hash, hashGetComp);
return (NULL != found)? *found : NULL;
return found;
}
// vim: set ts=4 sw=4:

9
src/hash/hash.c

@ -38,7 +38,7 @@ hashCtor(void * _this, va_list * params)
static
inline
void
tDelete(void * node)
tDelete(const void * node, const int depth)
{
delete(node);
}
@ -49,12 +49,7 @@ hashDtor(void * _this)
{
Hash this = _this;
/**
* this is a GNU extension...anyway on most non
* GNUish systems i would not use tsearch anyway
* as the trees will be unbalanced.
*/
tdestroy(this->root, tDelete);
treeDestroy(&this->root, tDelete);
}
INIT_IFACE(Class, hashCtor, hashDtor, NULL);

4
src/rbtree.c

@ -789,8 +789,8 @@ main(int argc, char * argv[])
traverse(root, printElement);
puts("");
post(root, cleanup);
// post(root, cleanup);
//
return 0;
}

144
src/rbtree2.c

@ -0,0 +1,144 @@
#include <stdio.h>
#include "class.h"
#include "commons.h"
#include "utils/memory.h"
#include "tree.h"
#define NVALUES 10
int
insertCompare(const void * tval, const void * search)
{
return *(const int *)tval - *(const int *)search;
}
void
printNode(const void * _node, const int depth)
{
//Tree node = (Tree)_node;
//int value = *(int *)node->data;
int value = *(int *)_node;
int i;
printf("%010d(%02d)", value, depth);
// printf("%s %010d(%02d)",
// (node->color==rbRed)?"R":"B",
// value,
// depth);
for (i=0; i<depth; i++) printf("-");
puts("");
}
/**
* =======================================================================
*/
int
main(int argc, char * argv[])
{
Tree root = NULL;
int * found = NULL;
int values[] = {40, 50, 60, 70, 80, 45, 75, 85};
int new50 = 50;
int new70 = 70;
int new80 = 80;
int search10 = 10;
int search64 = 64;
treeInsert(&root, (void *)&(values[0]), insertCompare);
treeInsert(&root, (void *)&(values[1]), insertCompare);
treeInsert(&root, (void *)&(values[2]), insertCompare);
treeInsert(&root, (void *)&(values[3]), insertCompare);
treeInsert(&root, (void *)&(values[4]), insertCompare);
treeInsert(&root, (void *)&(values[5]), insertCompare);
treeInsert(&root, (void *)&(values[6]), insertCompare);
treeInsert(&root, (void *)&(values[7]), insertCompare);
puts("traverse");
treeWalk(root, printNode);
puts("");
found = treeInsert(&root, (void *)&new70, insertCompare);
printf("insert %p(%d) got %p(%d)\n", &new70, new70, found, *found);
puts("traverse");
treeWalk(root, printNode);
puts("");
found = treeFind(root, &search10, insertCompare);
if (NULL == found) {
printf("can't find segmenet of minimum size: %d\n", 10);
} else {
printf("found %d\n", *found);
}
puts("");
found = treeFind(root, &search64, insertCompare);
if (NULL == found) {
printf("can't find segmenet of minimum size: %d\n", 64);
} else {
printf("found %d\n", *found);
}
puts("");
found = treeFind(root, &new70, insertCompare);
if (NULL == found) {
printf("can't find segmenet of minimum size: %d\n", 70);
} else {
printf("found %d\n", *found);
}
puts("");
found = treeDelete(&root, (void *)&new70, insertCompare);
printf("delete %p(%d) got %p(%d)\n", &new70, new70, found, *found);
puts("traverse");
treeWalk(root, printNode);
puts("");
found = treeInsert(&root, (void *)&new80, insertCompare);
printf("insert %p(%d) got %p(%d)\n", &new80, new80, found, *found);
found = treeInsert(&root, (void *)&new50, insertCompare);
printf("insert %p(%d) got %p(%d)\n", &new50, new50, found, *found);
found = treeInsert(&root, (void *)&new80, insertCompare);
printf("insert %p(%d) got %p(%d)\n", &new80, new80, found, *found);
puts("traverse");
treeWalk(root, printNode);
puts("");
found = treeDelete(&root, (void *)&new80, insertCompare);
printf("delete %p(%d) got %p(%d)\n", &new80, new80, found, *found);
puts("traverse");
treeWalk(root, printNode);
puts("");
found = treeDelete(&root, (void *)&new50, insertCompare);
printf("delete %p(%d) got %p(%d)\n", &new50, new50, found, *found);
puts("traverse");
treeWalk(root, printNode);
puts("");
found = treeDelete(&root, (void *)&new70, insertCompare);
printf("delete %p(%d) got %p(%d)\n", &new70, new70, found, found?*found:-1);
puts("traverse");
treeWalk(root, printNode);
puts("");
found = treeDelete(&root, (void *)&(values[2]), insertCompare);
printf("delete %p(%d) got %p(%d)\n",
&(values[2]),
values[2],
found,
found?*found:-1);
puts("traverse");
treeWalk(root, printNode);
puts("");
//
// post(root, cleanup);
return 0;
}
// vim: set et ts=4 sw=4:

6
src/server/run.c

@ -43,7 +43,11 @@ serverRun(Server this)
{
unsigned int i;
if (0 == events) {
if (0 <= events) {
/*
* TODO check why sometimes events is less than 0
* There is still a misshandling here.
*/
events = serverPoll(this);
}

9
src/tree/Makefile.am

@ -0,0 +1,9 @@
ACLOCAL_AMFLAGS = -I m4
TREE = tree.c find.c insert.c inOrderSuccessor.c delete.c walk.c \
rotateLeft.c rotateRight.c destroy.c
noinst_LIBRARIES = libtree.a
libtree_a_SOURCES = $(TREE)
libtree_a_CFLAGS = $(CFLAGS) -Wall -I ../../include/

248
src/tree/delete.c

@ -0,0 +1,248 @@
/**
* \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 "tree.h"
Tree inOrderSuccessor(Tree);
void treeRotateLeft(Tree *, Tree);
void treeRotateRight(Tree *, Tree);
void *
treeDelete(Tree * this, const void * search, TreeComp comp)
{
Tree node = *this;
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 = TREE_LEFT(node);
continue;
}
if (0 > comparison) {
node = TREE_RIGHT(node);
continue;
}
if (0 == comparison) {
break;
}
}
/*
* nothing was found...return NULL to indicate this.
*/
if (NULL == node) {
return NULL;
}
/*
* we found an element, store its data pointer as we are
* up to delete it.
*/
data = node->data;
/*
* now remove the element.
*/
/*
* if we have two children replace data with the one from
* out inOrderSuccessor and remove the inOrderSuccessor.
*/
if (NULL != TREE_LEFT(node) && NULL != TREE_RIGHT(node)) {
Tree successor = inOrderSuccessor(node);
node->data = successor->data;
node = successor;
}
{
Tree child = TREE_CHILD(node);
/*
* if we still have one child replace ourself with it.
*/
TREE_REPLACE_NODE(this, node, child);
/*
* and finally delete the node...and prepare ourselfs
* for rebalancing.
*/
if (rbBlack == node->color) {
if (NULL != child && rbRed == child->color) {
child->color = rbBlack;
delete(node);
return data;
} else {
if (NULL != child) {
node = child;
} else {
node->color = rbBlack;
node->left = NULL;
node->right = NULL;
}
}
} else {
delete(node);
return data;
}
}
/*
* now comes rebalancing...note that if we came to this point
* the node is still not deleted.
* This is because I am not sure if it is needed during the
* rebalancing process...(this does not make much sense, but
* to be honest I don't know now.)
*/
while(1) {
// case 1
if (NULL == TREE_PARENT(node)) {
break;
}
// case 2
if (NULL != TREE_SIBLING(node)
&& rbRed == TREE_SIBLING(node)->color) {
TREE_PARENT(node)->color = rbRed;
TREE_SIBLING(node)->color = rbBlack;
if (NULL != TREE_PARENT(node)->right &&
node != TREE_PARENT(node)->right) {
//TREE_ROTATE_LEFT(this, TREE_PARENT(node));
treeRotateLeft(this, TREE_PARENT(node));
} else {
//TREE_ROTATE_RIGHT(this, TREE_PARENT(node));
treeRotateRight(this, TREE_PARENT(node));
}
}
// case 3 / 4
if (NULL == TREE_SIBLING(node)
|| (rbBlack == TREE_SIBLING(node)->color
&& (NULL == TREE_SIBLING(node)->left
|| rbBlack == TREE_SIBLING(node)->left->color)
&& (NULL == TREE_SIBLING(node)->right
|| rbBlack == TREE_SIBLING(node)->right->color))) {
if (NULL != TREE_SIBLING(node)) {
TREE_SIBLING(node)->color = rbRed;
}
/*
* this is the point where during the balancing our tree
* node can be finally deleted.
*/
if (rbBlack == TREE_PARENT(node)->color) {
// case 3
Tree parent = node->parent;
delete(node);
node = parent;
continue;
} else {
// case 4
TREE_PARENT(node)->color = rbBlack;
delete(node);
break;
}
}
// case 5
if (NULL != TREE_SIBLING(node)
&& rbBlack == TREE_SIBLING(node)->color) {
if (node == TREE_PARENT(node)->left
&& (NULL == TREE_SIBLING(node)->right
|| rbBlack == TREE_SIBLING(node)->right->color)
&& (NULL != TREE_SIBLING(node)->left
&& rbRed == TREE_SIBLING(node)->left->color)) {
TREE_SIBLING(node)->color = rbRed;
TREE_SIBLING(node)->left->color = rbBlack;
//TREE_ROTATE_RIGHT(this, TREE_SIBLING(node));
treeRotateRight(this, TREE_SIBLING(node));
} else if (node == TREE_PARENT(node)->right
&& (NULL == TREE_SIBLING(node)->left
|| rbBlack == TREE_SIBLING(node)->left->color)
&& (NULL != TREE_SIBLING(node)->right
&& rbRed == TREE_SIBLING(node)->right->color)) {
TREE_SIBLING(node)->color = rbRed;
TREE_SIBLING(node)->right->color = rbBlack;
//TREE_ROTATE_LEFT(this, TREE_SIBLING(node));
treeRotateLeft(this, TREE_SIBLING(node));
}
}
// case 6
if (NULL != TREE_SIBLING(node)) {
TREE_SIBLING(node)->color = TREE_PARENT(node)->color;
}
if (NULL != node && NULL != TREE_PARENT(node)) {
TREE_PARENT(node)->color = rbBlack;
if (NULL != TREE_PARENT(node)->right
&& node != TREE_PARENT(node)->right) {
if (NULL != TREE_SIBLING(node)->right) {
TREE_SIBLING(node)->right->color = rbBlack;
}
//TREE_ROTATE_LEFT(this, TREE_PARENT(node));
treeRotateLeft(this, TREE_PARENT(node));
} else {
if (NULL != TREE_SIBLING(node)->left) {
TREE_SIBLING(node)->left->color = rbBlack;
}
//TREE_ROTATE_RIGHT(this, TREE_PARENT(node));
treeRotateRight(this, TREE_PARENT(node));
}
}
break;
}
/*
* not sure if deleting here is correct.
*/
return data;
}
// vim: set ts=4 sw=4:

84
src/tree/destroy.c

@ -0,0 +1,84 @@
/**
* \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 "tree.h"
void
treeDestroy(Tree * this, TreeAction action)
{
Tree previous = * this;
Tree node = * this;
int depth = 1;
/*
* I think this has something like O(n+log(n)) on a ballanced
* tree because I have to traverse back the rightmost leaf to
* the root to get a break condition.
*/
while (NULL != node) {
/*
* If we come from the right so nothing and go to our
* next parent.
*/
if ((NULL == TREE_LEFT(node) && NULL == TREE_RIGHT(node))
|| previous == TREE_RIGHT(node)) {
Tree parent = TREE_PARENT(node);
action(node->data, depth);
previous = node;
delete(node);
node = parent;
depth--;
continue;
}
if ((NULL == TREE_LEFT(node) || previous == TREE_LEFT(node))) {
/*
* If there are no more elements to the left or we
* came from the left, process data.
*/
previous = node;
if (NULL != TREE_RIGHT(node)) {
node = TREE_RIGHT(node);
depth++;
} else {
node = TREE_PARENT(node);
depth--;
}
} else {
/*
* if there are more elements to the left go there.
*/
previous = node;
node = TREE_LEFT(node);
depth++;
}
}
*this = NULL;
}
// vim: set ts=4 sw=4:

49
src/tree/find.c

@ -0,0 +1,49 @@
/**
* \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 "tree.h"
void *
treeFind(Tree this, const void * search, TreeComp comp)
{
while (NULL != this) {
int comparison = comp(this->data, search);
if (0 < comparison) {
this = TREE_LEFT(this);
continue;
}
if (0 > comparison) {
this = TREE_RIGHT(this);
continue;
}
if (0 == comparison) {
break;
}
}
return NULL != this ? this->data : NULL;
}
// vim: set ts=4 sw=4:

37
src/tree/inOrderSuccessor.c

@ -0,0 +1,37 @@
/**
* \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 "tree.h"
Tree
inOrderSuccessor(Tree this)
{
this = TREE_RIGHT(this);
while (NULL != TREE_LEFT(this)) {
this = TREE_LEFT(this);
}
return this;
}
// vim: set ts=4 sw=4:

152
src/tree/insert.c

@ -0,0 +1,152 @@
/**
* \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 "tree.h"
void treeRotateLeft(Tree *, Tree);
void treeRotateRight(Tree *, Tree);
void *
treeInsert(Tree * this, const void * search, TreeComp comp)
{
Tree node = *this;
Tree new_node = NULL;
/*
* insert the node or return the one in tree if comparison
* succeeds.
*/
if (NULL == node) {
/*
* if the root is NULL we simple add the element and set
* node to it.
*/
*this = node = new_node = new(Tree, search);
} else {
/*
* 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);
if (0 < comparison) {
if (NULL != TREE_LEFT(node)) {
node = TREE_LEFT(node);
continue;
} else {
break;
}
}
if (0 > comparison) {
if (NULL != TREE_RIGHT(node)) {
node = TREE_RIGHT(node);
continue;
} else {
break;
}
}
if (0 == comparison) {
return node->data;
}
}
/*
* as we have not found it now add a new element.
*/
if (0 < comparison) {
node->left = new(Tree, search);
TREE_LEFT(node)->parent = node;
node = new_node = TREE_LEFT(node);
} else {
node->right = new(Tree, search);
TREE_RIGHT(node)->parent = node;
node = new_node = TREE_RIGHT(node);
}
}
/*
* we expect node not to be NULL and pointing to our
* new node at this point...now rabalance the tree
*/
while (1) {
// case 1
if (NULL == TREE_PARENT(node)) {
node->color = rbBlack;
break;
}
// case 2
if (rbBlack == TREE_PARENT(node)->color) {
break;
}
// case 3
if (NULL != TREE_UNCLE(node) && rbRed == TREE_UNCLE(node)->color) {
TREE_PARENT(node)->color = rbBlack;
TREE_UNCLE(node)->color = rbBlack;
TREE_GRANDPARENT(node)->color = rbRed;
node = TREE_GRANDPARENT(node);
continue;
}
// case 4
if (node == TREE_PARENT(node)->right
&& TREE_PARENT(node) == TREE_GRANDPARENT(node)->left) {
//TREE_ROTATE_LEFT(this, TREE_PARENT(node));
treeRotateLeft(this, TREE_PARENT(node));
node = TREE_LEFT(node);
} else if (node == TREE_PARENT(node)->left
&& TREE_PARENT(node) == TREE_GRANDPARENT(node)->right) {
//TREE_ROTATE_RIGHT(this, TREE_PARENT(node));
treeRotateRight(this, TREE_PARENT(node));
node = TREE_RIGHT(node);
}
// case 5
TREE_PARENT(node)->color = rbBlack;
TREE_GRANDPARENT(node)->color = rbRed;
if (node == TREE_PARENT(node)->left) {
//TREE_ROTATE_RIGHT(this, TREE_GRANDPARENT(node));
treeRotateRight(this, TREE_GRANDPARENT(node));
} else {
//TREE_ROTATE_LEFT(this, TREE_GRANDPARENT(node));
treeRotateLeft(this, TREE_GRANDPARENT(node));
}
break;
}
return new_node->data;
}
// vim: set ts=4 sw=4:

51
src/tree/rotateLeft.c

@ -0,0 +1,51 @@
/**
* \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 "tree.h"
void
treeRotateLeft(Tree * this, Tree node)
{
Tree rightChild = TREE_RIGHT(node);
Tree rcLeftSub = TREE_RIGHT_LEFT(node);
rightChild->left = node;
rightChild->parent = TREE_PARENT(node);
node->right = rcLeftSub;
if (NULL != rcLeftSub) {
rcLeftSub->parent = node;
}
if (NULL != TREE_PARENT(node)) {
if (TREE_PARENT(node)->left == node) {
TREE_PARENT(node)->left = rightChild;
} else {
TREE_PARENT(node)->right = rightChild;
}
} else {
*this = rightChild;
}
node->parent = rightChild;
}
// vim: set ts=4 sw=4:

51
src/tree/rotateRight.c

@ -0,0 +1,51 @@
/**
* \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 "tree.h"
void
treeRotateRight(Tree * this, Tree node)
{
Tree leftChild = TREE_LEFT(node);
Tree lcRightSub = TREE_LEFT_RIGHT(node);
leftChild->right = node;
leftChild->parent = TREE_PARENT(node);
node->left = lcRightSub;
if (NULL != lcRightSub) {
lcRightSub->parent = node;
}
if (NULL != TREE_PARENT(node)) {
if (TREE_PARENT(node)->left == node) {
TREE_PARENT(node)->left = leftChild;
} else {
TREE_PARENT(node)->right = leftChild;
}
} else {
*this = leftChild;
}
node->parent = leftChild;
}
// vim: set ts=4 sw=4:

54
src/tree/tree.c

@ -0,0 +1,54 @@
/**
* \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/>.
*/
#define _GNU_SOURCE
#include <stdarg.h>
#include "tree.h"
#include "class.h"
static
int
treeCtor(void * _this, va_list * params)
{
Tree this = _this;
this->data = va_arg(*params, void *);
this->color = rbRed;
this->parent = NULL;
this->left = NULL;
this->right = NULL;
return 0;
}
static
void
treeDtor(void * _this)
{
}
INIT_IFACE(Class, treeCtor, treeDtor, NULL);
CREATE_CLASS(Tree, NULL, IFACE(Class));
// vim: set ts=4 sw=4:

59
src/tree/walk.c

@ -0,0 +1,59 @@
/**
* \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 "tree.h"
void
treeWalk(Tree this, TreeAction action)
{
Tree previous = this;
Tree node = this;
int depth = 1;
while (NULL != node) {
if (previous == TREE_RIGHT(node)) {
previous = node;
node = node->parent;
depth--;
continue;
}
if (NULL == TREE_LEFT(node) || previous == TREE_LEFT(node)) {
action(node->data, depth);
previous = node;
if (NULL != TREE_RIGHT(node)) {
node = TREE_RIGHT(node);
depth++;
} else {
node = TREE_PARENT(node);
depth--;
}
} else {
previous = node;
node = TREE_LEFT(node);
depth++;
}
}
}
// vim: set ts=4 sw=4:

8
src/utils/memory.c

@ -54,14 +54,12 @@
#include <unistd.h>
#include "utils/memory.h"
#include "tree.h"
#define PAGE_SIZE = 32
enum rbColor {rbBlack=1, rbRed=2};
struct memSegment
{
size_t size;
@ -394,8 +392,6 @@ findInOrderSuccessor(struct memSegment * tree)
return node;
}
struct memSegment * deleteOneChild(struct memSegment **, struct memSegment *);
struct memSegment *
deleteElement(struct memSegment ** tree, struct memSegment * element)
{
@ -619,8 +615,6 @@ deleteElement(struct memSegment ** tree, struct memSegment * element)
break;
}
//deleteOneChild(tree, node);
return del_node;
}

Loading…
Cancel
Save