Commit c8dc541c489ddcc37d543ca9c7a3b25ad569f260
1 parent
417b9f6d
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.
Showing
25 changed files
with
1144 additions
and
102 deletions
include/tree.h
0 → 100644
1 | +/** | |
2 | + * \file | |
3 | + * | |
4 | + * \author Georg Hopp | |
5 | + * | |
6 | + * \copyright | |
7 | + * Copyright © 2012 Georg Hopp | |
8 | + * | |
9 | + * This program is free software: you can redistribute it and/or modify | |
10 | + * it under the terms of the GNU General Public License as published by | |
11 | + * the Free Software Foundation, either version 3 of the License, or | |
12 | + * (at your option) any later version. | |
13 | + * | |
14 | + * This program is distributed in the hope that it will be useful, | |
15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | + * GNU General Public License for more details. | |
18 | + * | |
19 | + * You should have received a copy of the GNU General Public License | |
20 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
21 | + */ | |
22 | + | |
23 | +#ifndef __TREE_H__ | |
24 | +#define __TREE_H__ | |
25 | + | |
26 | +#include "class.h" | |
27 | + | |
28 | +#define TREE_RIGHT(node) (NULL!=(node)?(node)->right:NULL) | |
29 | +#define TREE_LEFT(node) (NULL!=(node)?(node)->left:NULL) | |
30 | +#define TREE_PARENT(node) (NULL!=(node)?(node)->parent:NULL) | |
31 | + | |
32 | +#define TREE_CHILD(node) \ | |
33 | + (NULL==TREE_RIGHT((node))?TREE_LEFT((node)):TREE_RIGHT((node))) | |
34 | + | |
35 | +#define TREE_RIGHT_LEFT(node) \ | |
36 | + (NULL!=TREE_RIGHT((node))?TREE_LEFT(TREE_RIGHT((node))):NULL) | |
37 | + | |
38 | +#define TREE_LEFT_RIGHT(node) \ | |
39 | + (NULL!=TREE_LEFT((node))?TREE_RIGHT(TREE_LEFT((node))):NULL) | |
40 | + | |
41 | +#define TREE_SIBLING(node) \ | |
42 | + (NULL!=TREE_PARENT((node))? \ | |
43 | + ((node)==TREE_PARENT((node))->left? \ | |
44 | + TREE_PARENT((node))->right: \ | |
45 | + TREE_PARENT((node))->left): \ | |
46 | + NULL) | |
47 | + | |
48 | +#define TREE_GRANDPARENT(node) \ | |
49 | + (NULL!=TREE_PARENT((node))?TREE_PARENT((node))->parent:NULL) | |
50 | + | |
51 | +#define TREE_UNCLE(node) \ | |
52 | + (NULL!=TREE_GRANDPARENT((node))? \ | |
53 | + (TREE_PARENT((node))==TREE_GRANDPARENT((node))->left? \ | |
54 | + TREE_GRANDPARENT((node))->right: \ | |
55 | + TREE_GRANDPARENT((node))->left): \ | |
56 | + NULL) | |
57 | + | |
58 | +#define TREE_ROTATE_LEFT(root, node) \ | |
59 | + do { \ | |
60 | + if (NULL != TREE_RIGHT_LEFT((node))) { \ | |
61 | + TREE_RIGHT_LEFT((node))->parent = (node); \ | |
62 | + } \ | |
63 | + TREE_RIGHT((node))->left = (node); \ | |
64 | + if (NULL != TREE_PARENT((node))) { \ | |
65 | + if (TREE_PARENT((node))->left==(node)) { \ | |
66 | + TREE_PARENT((node))->left = (node)->right; \ | |
67 | + } else { \ | |
68 | + TREE_PARENT((node))->right = (node)->right; \ | |
69 | + } \ | |
70 | + } else { \ | |
71 | + *(root) = (node)->right; \ | |
72 | + } \ | |
73 | + (node)->right = TREE_RIGHT_LEFT((node)); \ | |
74 | + (node)->parent = (node)->right; \ | |
75 | + TREE_RIGHT((node))->parent = (node)->parent; \ | |
76 | + } while(0) | |
77 | + | |
78 | +#define TREE_ROTATE_RIGHT(root, node) \ | |
79 | + do { \ | |
80 | + if (NULL != TREE_LEFT_RIGHT((node))) { \ | |
81 | + TREE_LEFT_RIGHT((node))->parent = (node); \ | |
82 | + } \ | |
83 | + TREE_LEFT((node))->right = (node); \ | |
84 | + if (NULL != TREE_PARENT((node))) { \ | |
85 | + if (TREE_PARENT((node))->left==(node)) { \ | |
86 | + TREE_PARENT((node))->left = (node)->left; \ | |
87 | + } else { \ | |
88 | + TREE_PARENT((node))->right = (node)->left; \ | |
89 | + } \ | |
90 | + } else { \ | |
91 | + *(root) = (node)->left; \ | |
92 | + } \ | |
93 | + TREE_LEFT((node))->parent = (node)->parent; \ | |
94 | + (node)->left = TREE_LEFT_RIGHT((node)); \ | |
95 | + (node)->parent = (node)->right; \ | |
96 | + } while(0) | |
97 | + | |
98 | +#define TREE_REPLACE_NODE(root, node1, node2) \ | |
99 | + do { \ | |
100 | + if (NULL != TREE_PARENT((node1))) { \ | |
101 | + if ((node1) == TREE_PARENT((node1))->left) { \ | |
102 | + TREE_PARENT((node1))->left = (node2); \ | |
103 | + } else { \ | |
104 | + TREE_PARENT((node1))->right = (node2); \ | |
105 | + } \ | |
106 | + } else { \ | |
107 | + *(root) = (node2); \ | |
108 | + } \ | |
109 | + if (NULL != (node2)) { \ | |
110 | + (node2)->parent = (node1)->parent; \ | |
111 | + } \ | |
112 | + } while(0) | |
113 | + | |
114 | + | |
115 | +enum rbColor {rbBlack=1, rbRed=2}; | |
116 | + | |
117 | +CLASS(Tree) { | |
118 | + void * data; | |
119 | + | |
120 | + enum rbColor color; | |
121 | + | |
122 | + Tree parent; | |
123 | + Tree left; | |
124 | + Tree right; | |
125 | +}; | |
126 | + | |
127 | +typedef int (*TreeComp)(const void *, const void *); | |
128 | +typedef void (*TreeAction)(const void *, const int); | |
129 | + | |
130 | +void * treeFind(Tree, const void *, TreeComp); | |
131 | +void * treeInsert(Tree *, const void *, TreeComp); | |
132 | +void * treeDelete(Tree *, const void *, TreeComp); | |
133 | +void treeWalk(Tree, TreeAction); | |
134 | +void treeDestroy(Tree *, TreeAction); | |
135 | + | |
136 | +#endif // __TREE_H__ | |
137 | + | |
138 | +// vim: set ts=4 sw=4: | ... | ... |
... | ... | @@ -21,7 +21,8 @@ LIBS = ./http/libhttp.a \ |
21 | 21 | ./server/libserver.a \ |
22 | 22 | ./session/libsession.a \ |
23 | 23 | ./socket/libsocket.a \ |
24 | - ./stream/libstream.a | |
24 | + ./stream/libstream.a \ | |
25 | + ./tree/libtree.a | |
25 | 26 | |
26 | 27 | AM_CFLAGS = -Wall -I ../include/ |
27 | 28 | |
... | ... | @@ -33,4 +34,4 @@ taskrambler_LDADD = $(LIBS) -lrt -lssl -lldap |
33 | 34 | #taskrambler_LDFLAGS = $(COVERAGE_LDFLAGS) |
34 | 35 | |
35 | 36 | SUBDIRS = asset auth cbuf class hash queue http \ |
36 | - logger server session socket stream | |
37 | + logger server session socket stream tree | ... | ... |
... | ... | @@ -20,10 +20,6 @@ |
20 | 20 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
21 | 21 | */ |
22 | 22 | |
23 | -// for debug | |
24 | -#include <stdio.h> | |
25 | - | |
26 | - | |
27 | 23 | #include <stdarg.h> |
28 | 24 | |
29 | 25 | // for mmap |
... | ... | @@ -105,9 +101,6 @@ assetCtor(void * _this, va_list * params) |
105 | 101 | return -1; |
106 | 102 | } |
107 | 103 | |
108 | - printf("DEBUG file mapped from %p to %p\n", | |
109 | - this->data, this->data + this->size); | |
110 | - | |
111 | 104 | this->ref_count = 1; |
112 | 105 | |
113 | 106 | return 0; | ... | ... |
... | ... | @@ -20,9 +20,6 @@ |
20 | 20 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
21 | 21 | */ |
22 | 22 | |
23 | -// for debugging | |
24 | -#include <stdio.h> | |
25 | - | |
26 | 23 | // for size_t |
27 | 24 | #include <sys/types.h> |
28 | 25 | |
... | ... | @@ -47,8 +44,6 @@ assetPoolGet(const char * path, size_t npath) |
47 | 44 | { |
48 | 45 | Asset asset = NULL; |
49 | 46 | |
50 | - printf("DEBUG: pool get asset --%s--\n", path); | |
51 | - | |
52 | 47 | if (NULL == asset_pool) { |
53 | 48 | asset_pool = new(Hash); |
54 | 49 | } else { |
... | ... | @@ -57,12 +52,9 @@ assetPoolGet(const char * path, size_t npath) |
57 | 52 | |
58 | 53 | if (NULL == asset) { |
59 | 54 | asset = new(Asset, path, npath); |
60 | - printf("DEBUG create asset %p\n", asset); | |
61 | 55 | hashAdd(asset_pool, asset); |
62 | 56 | } else { |
63 | - printf("DEBUG found asset %p\n", asset); | |
64 | 57 | asset->ref_count++; |
65 | - printf("DEBUG increase ref_count to %zu\n", asset->ref_count); | |
66 | 58 | } |
67 | 59 | |
68 | 60 | return asset; |
... | ... | @@ -71,19 +63,20 @@ assetPoolGet(const char * path, size_t npath) |
71 | 63 | size_t |
72 | 64 | assetPoolRelease(Asset asset) |
73 | 65 | { |
74 | - printf("DEBUG: pool release asset --%s--\n", asset->fname); | |
75 | - | |
76 | 66 | if (asset->ref_count > 1) { |
77 | 67 | asset->ref_count--; |
78 | - printf("DEBUG decrease ref_count to %zu\n", asset->ref_count); | |
79 | 68 | return asset->ref_count; |
80 | 69 | } |
81 | 70 | |
82 | 71 | if (NULL != asset) { |
83 | 72 | Asset found = (Asset)hashDelete( |
84 | 73 | asset_pool, asset->fname, asset->nfname); |
85 | - printf("DEBUG delete %p, parent was %p\n", asset, found); | |
86 | - delete(asset); | |
74 | + | |
75 | + if (found == asset) { | |
76 | + delete(found); | |
77 | + } else { | |
78 | + // this should never happen....error log... | |
79 | + } | |
87 | 80 | } |
88 | 81 | |
89 | 82 | return 0; | ... | ... |
... | ... | @@ -30,24 +30,35 @@ inline |
30 | 30 | int |
31 | 31 | hashAddComp(const void * a, const void * b) |
32 | 32 | { |
33 | - return hashableGetHash((void*)b) - hashableGetHash((void*)a); | |
33 | + unsigned long hash_a = hashableGetHash((void*)a); | |
34 | + unsigned long hash_b = hashableGetHash((void*)b); | |
35 | + | |
36 | + if (hash_a < hash_b) { | |
37 | + return -1; | |
38 | + } | |
39 | + | |
40 | + if (hash_a > hash_b) { | |
41 | + return 1; | |
42 | + } | |
43 | + | |
44 | + return 0; | |
34 | 45 | } |
35 | 46 | |
36 | 47 | void * |
37 | 48 | hashAdd(Hash this, void * operand) |
38 | 49 | { |
39 | - void * found = tsearch(operand, &(this->root), hashAddComp); | |
50 | + void * found = treeInsert(&this->root, operand, hashAddComp); | |
40 | 51 | |
41 | 52 | if (NULL == found) { |
42 | 53 | return NULL; |
43 | 54 | } |
44 | 55 | |
45 | - if (operand != *(void**)found) { | |
46 | - hashableHandleDouble(*(void**)found, operand); | |
56 | + if (operand != found) { | |
57 | + hashableHandleDouble(found, operand); | |
47 | 58 | delete(operand); |
48 | 59 | } |
49 | 60 | |
50 | - return *(void**)found; | |
61 | + return found; | |
51 | 62 | } |
52 | 63 | |
53 | 64 | // vim: set ts=4 sw=4: | ... | ... |
... | ... | @@ -20,9 +20,6 @@ |
20 | 20 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
21 | 21 | */ |
22 | 22 | |
23 | -#include <stdio.h> | |
24 | - | |
25 | -#include <search.h> | |
26 | 23 | #include <sys/types.h> |
27 | 24 | |
28 | 25 | #include "asset.h" |
... | ... | @@ -34,59 +31,26 @@ inline |
34 | 31 | int |
35 | 32 | hashDeleteComp(const void * a, const void * b) |
36 | 33 | { |
37 | - if (_Asset == GET_CLASS(b)) { | |
38 | - Asset data = (Asset)b; | |
39 | - printf("DEBUG: search asset hash: %lu\n", | |
40 | - *(const unsigned long*)a); | |
41 | - printf("DEBUG: found: %lu, key: %s\n", | |
42 | - data->hash, data->fname); | |
43 | - } | |
44 | - | |
45 | - return hashableGetHash((void*)b) - *(const unsigned long*)a; | |
46 | -} | |
47 | - | |
48 | -void | |
49 | -action(const void *nodep, const VISIT which, const int depth) | |
50 | -{ | |
51 | - void * datap = *(void **)nodep; | |
52 | - | |
53 | - if (_Asset == GET_CLASS(datap)) { | |
54 | - Asset data = (Asset)datap; | |
34 | + unsigned long hash_a = hashableGetHash((void*)a); | |
55 | 35 | |
56 | - switch (which) { | |
57 | - case preorder: | |
58 | - break; | |
59 | - case postorder: | |
60 | - printf("DEBUG: %s(%lu) => %p\n", data->fname, data->hash, data); | |
61 | - break; | |
62 | - case endorder: | |
63 | - break; | |
64 | - case leaf: | |
65 | - printf("DEBUG: %s(%lu) => %p\n", data->fname, data->hash, data); | |
66 | - break; | |
67 | - } | |
36 | + if (hash_a < *(const unsigned long*)b) { | |
37 | + return -1; | |
38 | + } | |
39 | + | |
40 | + if (hash_a > *(const unsigned long*)b) { | |
41 | + return 1; | |
68 | 42 | } |
43 | + | |
44 | + return 0; | |
69 | 45 | } |
70 | 46 | |
71 | 47 | void * |
72 | 48 | hashDelete(Hash this, const char * search, size_t nsearch) |
73 | 49 | { |
74 | - unsigned long hash = sdbm((const unsigned char *)search, nsearch); | |
75 | - void * found = NULL; | |
76 | - int count = 0; | |
50 | + unsigned long hash = sdbm((const unsigned char *)search, nsearch); | |
51 | + void * found = NULL; | |
77 | 52 | |
78 | - twalk(this->root, action); | |
79 | - while (found == NULL && count < 3) { | |
80 | - found = tdelete(&hash, &(this->root), hashDeleteComp); | |
81 | - if (found == NULL) { | |
82 | - puts("DEBUG: !!!!! NOT FOUND !!!!!!!"); | |
83 | - void * found = hashGet(this, search, nsearch); | |
84 | - printf("DEBUG: find results in %p\n", found); | |
85 | - } | |
86 | - count++; | |
87 | - } | |
88 | - puts("==="); | |
89 | - twalk(this->root, action); | |
53 | + found = treeDelete(&(this->root), &hash, hashDeleteComp); | |
90 | 54 | |
91 | 55 | return found; |
92 | 56 | } | ... | ... |
... | ... | @@ -29,11 +29,9 @@ static void (*cb)(const void*); |
29 | 29 | static |
30 | 30 | inline |
31 | 31 | void |
32 | -walk(const void * node, const VISIT which, const int depth) | |
32 | +walk(const void * node, const int depth) | |
33 | 33 | { |
34 | - if (endorder == which || leaf == which) { | |
35 | - cb(*(void**)node); | |
36 | - } | |
34 | + cb(node); | |
37 | 35 | } |
38 | 36 | |
39 | 37 | void |
... | ... | @@ -41,7 +39,7 @@ hashEach(Hash this, void (*callback)(const void*)) |
41 | 39 | { |
42 | 40 | cb = callback; |
43 | 41 | |
44 | - twalk(this->root, walk); | |
42 | + treeWalk(this->root, walk); | |
45 | 43 | } |
46 | 44 | |
47 | 45 | // vim: set ts=4 sw=4: | ... | ... |
... | ... | @@ -26,6 +26,7 @@ |
26 | 26 | #include <sys/types.h> |
27 | 27 | |
28 | 28 | #include "hash.h" |
29 | +#include "tree.h" | |
29 | 30 | #include "utils/hash.h" |
30 | 31 | |
31 | 32 | static |
... | ... | @@ -33,16 +34,26 @@ inline |
33 | 34 | int |
34 | 35 | hashGetComp(const void * a, const void * b) |
35 | 36 | { |
36 | - return hashableGetHash((void*)b) - *(const unsigned long*)a; | |
37 | + unsigned long hash_a = hashableGetHash((void*)a); | |
38 | + | |
39 | + if (hash_a < *(const unsigned long*)b) { | |
40 | + return -1; | |
41 | + } | |
42 | + | |
43 | + if (hash_a > *(const unsigned long*)b) { | |
44 | + return 1; | |
45 | + } | |
46 | + | |
47 | + return 0; | |
37 | 48 | } |
38 | 49 | |
39 | 50 | void * |
40 | 51 | hashGet(Hash this, const char * search, size_t nsearch) |
41 | 52 | { |
42 | - unsigned long hash = sdbm((const unsigned char *)search, nsearch); | |
43 | - void ** found = tfind(&hash, &(this->root), hashGetComp); | |
53 | + unsigned long hash = sdbm((const unsigned char *)search, nsearch); | |
54 | + void * found = treeFind(this->root, &hash, hashGetComp); | |
44 | 55 | |
45 | - return (NULL != found)? *found : NULL; | |
56 | + return found; | |
46 | 57 | } |
47 | 58 | |
48 | 59 | // vim: set ts=4 sw=4: | ... | ... |
... | ... | @@ -38,7 +38,7 @@ hashCtor(void * _this, va_list * params) |
38 | 38 | static |
39 | 39 | inline |
40 | 40 | void |
41 | -tDelete(void * node) | |
41 | +tDelete(const void * node, const int depth) | |
42 | 42 | { |
43 | 43 | delete(node); |
44 | 44 | } |
... | ... | @@ -49,12 +49,7 @@ hashDtor(void * _this) |
49 | 49 | { |
50 | 50 | Hash this = _this; |
51 | 51 | |
52 | - /** | |
53 | - * this is a GNU extension...anyway on most non | |
54 | - * GNUish systems i would not use tsearch anyway | |
55 | - * as the trees will be unbalanced. | |
56 | - */ | |
57 | - tdestroy(this->root, tDelete); | |
52 | + treeDestroy(&this->root, tDelete); | |
58 | 53 | } |
59 | 54 | |
60 | 55 | INIT_IFACE(Class, hashCtor, hashDtor, NULL); | ... | ... |
src/rbtree2.c
0 → 100644
1 | +#include <stdio.h> | |
2 | + | |
3 | +#include "class.h" | |
4 | +#include "commons.h" | |
5 | +#include "utils/memory.h" | |
6 | + | |
7 | +#include "tree.h" | |
8 | + | |
9 | +#define NVALUES 10 | |
10 | + | |
11 | +int | |
12 | +insertCompare(const void * tval, const void * search) | |
13 | +{ | |
14 | + return *(const int *)tval - *(const int *)search; | |
15 | +} | |
16 | + | |
17 | +void | |
18 | +printNode(const void * _node, const int depth) | |
19 | +{ | |
20 | + //Tree node = (Tree)_node; | |
21 | + //int value = *(int *)node->data; | |
22 | + int value = *(int *)_node; | |
23 | + int i; | |
24 | + | |
25 | + printf("%010d(%02d)", value, depth); | |
26 | + | |
27 | + // printf("%s %010d(%02d)", | |
28 | + // (node->color==rbRed)?"R":"B", | |
29 | + // value, | |
30 | + // depth); | |
31 | + for (i=0; i<depth; i++) printf("-"); | |
32 | + puts(""); | |
33 | +} | |
34 | + | |
35 | + | |
36 | +/** | |
37 | + * ======================================================================= | |
38 | + */ | |
39 | +int | |
40 | +main(int argc, char * argv[]) | |
41 | +{ | |
42 | + Tree root = NULL; | |
43 | + int * found = NULL; | |
44 | + int values[] = {40, 50, 60, 70, 80, 45, 75, 85}; | |
45 | + int new50 = 50; | |
46 | + int new70 = 70; | |
47 | + int new80 = 80; | |
48 | + int search10 = 10; | |
49 | + int search64 = 64; | |
50 | + | |
51 | + treeInsert(&root, (void *)&(values[0]), insertCompare); | |
52 | + treeInsert(&root, (void *)&(values[1]), insertCompare); | |
53 | + treeInsert(&root, (void *)&(values[2]), insertCompare); | |
54 | + treeInsert(&root, (void *)&(values[3]), insertCompare); | |
55 | + treeInsert(&root, (void *)&(values[4]), insertCompare); | |
56 | + treeInsert(&root, (void *)&(values[5]), insertCompare); | |
57 | + treeInsert(&root, (void *)&(values[6]), insertCompare); | |
58 | + treeInsert(&root, (void *)&(values[7]), insertCompare); | |
59 | + puts("traverse"); | |
60 | + treeWalk(root, printNode); | |
61 | + puts(""); | |
62 | + | |
63 | + found = treeInsert(&root, (void *)&new70, insertCompare); | |
64 | + printf("insert %p(%d) got %p(%d)\n", &new70, new70, found, *found); | |
65 | + puts("traverse"); | |
66 | + treeWalk(root, printNode); | |
67 | + puts(""); | |
68 | + | |
69 | + found = treeFind(root, &search10, insertCompare); | |
70 | + if (NULL == found) { | |
71 | + printf("can't find segmenet of minimum size: %d\n", 10); | |
72 | + } else { | |
73 | + printf("found %d\n", *found); | |
74 | + } | |
75 | + puts(""); | |
76 | + | |
77 | + found = treeFind(root, &search64, insertCompare); | |
78 | + if (NULL == found) { | |
79 | + printf("can't find segmenet of minimum size: %d\n", 64); | |
80 | + } else { | |
81 | + printf("found %d\n", *found); | |
82 | + } | |
83 | + puts(""); | |
84 | + | |
85 | + found = treeFind(root, &new70, insertCompare); | |
86 | + if (NULL == found) { | |
87 | + printf("can't find segmenet of minimum size: %d\n", 70); | |
88 | + } else { | |
89 | + printf("found %d\n", *found); | |
90 | + } | |
91 | + puts(""); | |
92 | + | |
93 | + found = treeDelete(&root, (void *)&new70, insertCompare); | |
94 | + printf("delete %p(%d) got %p(%d)\n", &new70, new70, found, *found); | |
95 | + puts("traverse"); | |
96 | + treeWalk(root, printNode); | |
97 | + puts(""); | |
98 | + | |
99 | + found = treeInsert(&root, (void *)&new80, insertCompare); | |
100 | + printf("insert %p(%d) got %p(%d)\n", &new80, new80, found, *found); | |
101 | + found = treeInsert(&root, (void *)&new50, insertCompare); | |
102 | + printf("insert %p(%d) got %p(%d)\n", &new50, new50, found, *found); | |
103 | + found = treeInsert(&root, (void *)&new80, insertCompare); | |
104 | + printf("insert %p(%d) got %p(%d)\n", &new80, new80, found, *found); | |
105 | + | |
106 | + puts("traverse"); | |
107 | + treeWalk(root, printNode); | |
108 | + puts(""); | |
109 | + | |
110 | + found = treeDelete(&root, (void *)&new80, insertCompare); | |
111 | + printf("delete %p(%d) got %p(%d)\n", &new80, new80, found, *found); | |
112 | + puts("traverse"); | |
113 | + treeWalk(root, printNode); | |
114 | + puts(""); | |
115 | + | |
116 | + found = treeDelete(&root, (void *)&new50, insertCompare); | |
117 | + printf("delete %p(%d) got %p(%d)\n", &new50, new50, found, *found); | |
118 | + puts("traverse"); | |
119 | + treeWalk(root, printNode); | |
120 | + puts(""); | |
121 | + | |
122 | + found = treeDelete(&root, (void *)&new70, insertCompare); | |
123 | + printf("delete %p(%d) got %p(%d)\n", &new70, new70, found, found?*found:-1); | |
124 | + puts("traverse"); | |
125 | + treeWalk(root, printNode); | |
126 | + puts(""); | |
127 | + | |
128 | + found = treeDelete(&root, (void *)&(values[2]), insertCompare); | |
129 | + printf("delete %p(%d) got %p(%d)\n", | |
130 | + &(values[2]), | |
131 | + values[2], | |
132 | + found, | |
133 | + found?*found:-1); | |
134 | + puts("traverse"); | |
135 | + treeWalk(root, printNode); | |
136 | + puts(""); | |
137 | + | |
138 | +// | |
139 | +// post(root, cleanup); | |
140 | + | |
141 | + return 0; | |
142 | +} | |
143 | + | |
144 | +// vim: set et ts=4 sw=4: | ... | ... |
... | ... | @@ -43,7 +43,11 @@ serverRun(Server this) |
43 | 43 | { |
44 | 44 | unsigned int i; |
45 | 45 | |
46 | - if (0 == events) { | |
46 | + if (0 <= events) { | |
47 | + /* | |
48 | + * TODO check why sometimes events is less than 0 | |
49 | + * There is still a misshandling here. | |
50 | + */ | |
47 | 51 | events = serverPoll(this); |
48 | 52 | } |
49 | 53 | ... | ... |
src/tree/Makefile.am
0 → 100644
src/tree/delete.c
0 → 100644
1 | +/** | |
2 | + * \file | |
3 | + * | |
4 | + * \author Georg Hopp | |
5 | + * | |
6 | + * \copyright | |
7 | + * Copyright © 2012 Georg Hopp | |
8 | + * | |
9 | + * This program is free software: you can redistribute it and/or modify | |
10 | + * it under the terms of the GNU General Public License as published by | |
11 | + * the Free Software Foundation, either version 3 of the License, or | |
12 | + * (at your option) any later version. | |
13 | + * | |
14 | + * This program is distributed in the hope that it will be useful, | |
15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | + * GNU General Public License for more details. | |
18 | + * | |
19 | + * You should have received a copy of the GNU General Public License | |
20 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
21 | + */ | |
22 | + | |
23 | +#include "tree.h" | |
24 | + | |
25 | +Tree inOrderSuccessor(Tree); | |
26 | +void treeRotateLeft(Tree *, Tree); | |
27 | +void treeRotateRight(Tree *, Tree); | |
28 | + | |
29 | + | |
30 | +void * | |
31 | +treeDelete(Tree * this, const void * search, TreeComp comp) | |
32 | +{ | |
33 | + Tree node = *this; | |
34 | + | |
35 | + void * data; | |
36 | + | |
37 | + /* | |
38 | + * first search for it and if its found return the data | |
39 | + * and we are done... | |
40 | + */ | |
41 | + while (NULL != node) { | |
42 | + int comparison = comp(node->data, search); | |
43 | + | |
44 | + if (0 < comparison) { | |
45 | + node = TREE_LEFT(node); | |
46 | + continue; | |
47 | + } | |
48 | + | |
49 | + if (0 > comparison) { | |
50 | + node = TREE_RIGHT(node); | |
51 | + continue; | |
52 | + } | |
53 | + | |
54 | + if (0 == comparison) { | |
55 | + break; | |
56 | + } | |
57 | + } | |
58 | + | |
59 | + /* | |
60 | + * nothing was found...return NULL to indicate this. | |
61 | + */ | |
62 | + if (NULL == node) { | |
63 | + return NULL; | |
64 | + } | |
65 | + | |
66 | + /* | |
67 | + * we found an element, store its data pointer as we are | |
68 | + * up to delete it. | |
69 | + */ | |
70 | + data = node->data; | |
71 | + | |
72 | + /* | |
73 | + * now remove the element. | |
74 | + */ | |
75 | + | |
76 | + /* | |
77 | + * if we have two children replace data with the one from | |
78 | + * out inOrderSuccessor and remove the inOrderSuccessor. | |
79 | + */ | |
80 | + if (NULL != TREE_LEFT(node) && NULL != TREE_RIGHT(node)) { | |
81 | + Tree successor = inOrderSuccessor(node); | |
82 | + | |
83 | + node->data = successor->data; | |
84 | + node = successor; | |
85 | + } | |
86 | + | |
87 | + { | |
88 | + Tree child = TREE_CHILD(node); | |
89 | + | |
90 | + /* | |
91 | + * if we still have one child replace ourself with it. | |
92 | + */ | |
93 | + TREE_REPLACE_NODE(this, node, child); | |
94 | + | |
95 | + /* | |
96 | + * and finally delete the node...and prepare ourselfs | |
97 | + * for rebalancing. | |
98 | + */ | |
99 | + if (rbBlack == node->color) { | |
100 | + if (NULL != child && rbRed == child->color) { | |
101 | + child->color = rbBlack; | |
102 | + delete(node); | |
103 | + return data; | |
104 | + } else { | |
105 | + if (NULL != child) { | |
106 | + node = child; | |
107 | + } else { | |
108 | + node->color = rbBlack; | |
109 | + node->left = NULL; | |
110 | + node->right = NULL; | |
111 | + } | |
112 | + } | |
113 | + } else { | |
114 | + delete(node); | |
115 | + return data; | |
116 | + } | |
117 | + } | |
118 | + | |
119 | + /* | |
120 | + * now comes rebalancing...note that if we came to this point | |
121 | + * the node is still not deleted. | |
122 | + * This is because I am not sure if it is needed during the | |
123 | + * rebalancing process...(this does not make much sense, but | |
124 | + * to be honest I don't know now.) | |
125 | + */ | |
126 | + while(1) { | |
127 | + // case 1 | |
128 | + if (NULL == TREE_PARENT(node)) { | |
129 | + break; | |
130 | + } | |
131 | + | |
132 | + // case 2 | |
133 | + if (NULL != TREE_SIBLING(node) | |
134 | + && rbRed == TREE_SIBLING(node)->color) { | |
135 | + | |
136 | + TREE_PARENT(node)->color = rbRed; | |
137 | + TREE_SIBLING(node)->color = rbBlack; | |
138 | + | |
139 | + if (NULL != TREE_PARENT(node)->right && | |
140 | + node != TREE_PARENT(node)->right) { | |
141 | + | |
142 | + //TREE_ROTATE_LEFT(this, TREE_PARENT(node)); | |
143 | + treeRotateLeft(this, TREE_PARENT(node)); | |
144 | + | |
145 | + } else { | |
146 | + | |
147 | + //TREE_ROTATE_RIGHT(this, TREE_PARENT(node)); | |
148 | + treeRotateRight(this, TREE_PARENT(node)); | |
149 | + | |
150 | + } | |
151 | + } | |
152 | + | |
153 | + // case 3 / 4 | |
154 | + if (NULL == TREE_SIBLING(node) | |
155 | + || (rbBlack == TREE_SIBLING(node)->color | |
156 | + && (NULL == TREE_SIBLING(node)->left | |
157 | + || rbBlack == TREE_SIBLING(node)->left->color) | |
158 | + && (NULL == TREE_SIBLING(node)->right | |
159 | + || rbBlack == TREE_SIBLING(node)->right->color))) { | |
160 | + | |
161 | + if (NULL != TREE_SIBLING(node)) { | |
162 | + TREE_SIBLING(node)->color = rbRed; | |
163 | + } | |
164 | + | |
165 | + | |
166 | + /* | |
167 | + * this is the point where during the balancing our tree | |
168 | + * node can be finally deleted. | |
169 | + */ | |
170 | + if (rbBlack == TREE_PARENT(node)->color) { | |
171 | + // case 3 | |
172 | + Tree parent = node->parent; | |
173 | + delete(node); | |
174 | + node = parent; | |
175 | + continue; | |
176 | + } else { | |
177 | + // case 4 | |
178 | + TREE_PARENT(node)->color = rbBlack; | |
179 | + delete(node); | |
180 | + break; | |
181 | + } | |
182 | + } | |
183 | + | |
184 | + // case 5 | |
185 | + if (NULL != TREE_SIBLING(node) | |
186 | + && rbBlack == TREE_SIBLING(node)->color) { | |
187 | + | |
188 | + if (node == TREE_PARENT(node)->left | |
189 | + && (NULL == TREE_SIBLING(node)->right | |
190 | + || rbBlack == TREE_SIBLING(node)->right->color) | |
191 | + && (NULL != TREE_SIBLING(node)->left | |
192 | + && rbRed == TREE_SIBLING(node)->left->color)) { | |
193 | + | |
194 | + TREE_SIBLING(node)->color = rbRed; | |
195 | + TREE_SIBLING(node)->left->color = rbBlack; | |
196 | + | |
197 | + //TREE_ROTATE_RIGHT(this, TREE_SIBLING(node)); | |
198 | + treeRotateRight(this, TREE_SIBLING(node)); | |
199 | + | |
200 | + } else if (node == TREE_PARENT(node)->right | |
201 | + && (NULL == TREE_SIBLING(node)->left | |
202 | + || rbBlack == TREE_SIBLING(node)->left->color) | |
203 | + && (NULL != TREE_SIBLING(node)->right | |
204 | + && rbRed == TREE_SIBLING(node)->right->color)) { | |
205 | + | |
206 | + TREE_SIBLING(node)->color = rbRed; | |
207 | + TREE_SIBLING(node)->right->color = rbBlack; | |
208 | + | |
209 | + //TREE_ROTATE_LEFT(this, TREE_SIBLING(node)); | |
210 | + treeRotateLeft(this, TREE_SIBLING(node)); | |
211 | + } | |
212 | + } | |
213 | + | |
214 | + // case 6 | |
215 | + if (NULL != TREE_SIBLING(node)) { | |
216 | + TREE_SIBLING(node)->color = TREE_PARENT(node)->color; | |
217 | + } | |
218 | + | |
219 | + if (NULL != node && NULL != TREE_PARENT(node)) { | |
220 | + TREE_PARENT(node)->color = rbBlack; | |
221 | + | |
222 | + if (NULL != TREE_PARENT(node)->right | |
223 | + && node != TREE_PARENT(node)->right) { | |
224 | + | |
225 | + if (NULL != TREE_SIBLING(node)->right) { | |
226 | + TREE_SIBLING(node)->right->color = rbBlack; | |
227 | + } | |
228 | + //TREE_ROTATE_LEFT(this, TREE_PARENT(node)); | |
229 | + treeRotateLeft(this, TREE_PARENT(node)); | |
230 | + } else { | |
231 | + if (NULL != TREE_SIBLING(node)->left) { | |
232 | + TREE_SIBLING(node)->left->color = rbBlack; | |
233 | + } | |
234 | + //TREE_ROTATE_RIGHT(this, TREE_PARENT(node)); | |
235 | + treeRotateRight(this, TREE_PARENT(node)); | |
236 | + } | |
237 | + } | |
238 | + | |
239 | + break; | |
240 | + } | |
241 | + | |
242 | + /* | |
243 | + * not sure if deleting here is correct. | |
244 | + */ | |
245 | + return data; | |
246 | +} | |
247 | + | |
248 | +// vim: set ts=4 sw=4: | ... | ... |
src/tree/destroy.c
0 → 100644
1 | +/** | |
2 | + * \file | |
3 | + * | |
4 | + * \author Georg Hopp | |
5 | + * | |
6 | + * \copyright | |
7 | + * Copyright © 2012 Georg Hopp | |
8 | + * | |
9 | + * This program is free software: you can redistribute it and/or modify | |
10 | + * it under the terms of the GNU General Public License as published by | |
11 | + * the Free Software Foundation, either version 3 of the License, or | |
12 | + * (at your option) any later version. | |
13 | + * | |
14 | + * This program is distributed in the hope that it will be useful, | |
15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | + * GNU General Public License for more details. | |
18 | + * | |
19 | + * You should have received a copy of the GNU General Public License | |
20 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
21 | + */ | |
22 | + | |
23 | +#include "tree.h" | |
24 | + | |
25 | +void | |
26 | +treeDestroy(Tree * this, TreeAction action) | |
27 | +{ | |
28 | + Tree previous = * this; | |
29 | + Tree node = * this; | |
30 | + int depth = 1; | |
31 | + | |
32 | + /* | |
33 | + * I think this has something like O(n+log(n)) on a ballanced | |
34 | + * tree because I have to traverse back the rightmost leaf to | |
35 | + * the root to get a break condition. | |
36 | + */ | |
37 | + while (NULL != node) { | |
38 | + /* | |
39 | + * If we come from the right so nothing and go to our | |
40 | + * next parent. | |
41 | + */ | |
42 | + if ((NULL == TREE_LEFT(node) && NULL == TREE_RIGHT(node)) | |
43 | + || previous == TREE_RIGHT(node)) { | |
44 | + | |
45 | + Tree parent = TREE_PARENT(node); | |
46 | + | |
47 | + action(node->data, depth); | |
48 | + | |
49 | + previous = node; | |
50 | + delete(node); | |
51 | + node = parent; | |
52 | + depth--; | |
53 | + | |
54 | + continue; | |
55 | + } | |
56 | + | |
57 | + if ((NULL == TREE_LEFT(node) || previous == TREE_LEFT(node))) { | |
58 | + /* | |
59 | + * If there are no more elements to the left or we | |
60 | + * came from the left, process data. | |
61 | + */ | |
62 | + previous = node; | |
63 | + | |
64 | + if (NULL != TREE_RIGHT(node)) { | |
65 | + node = TREE_RIGHT(node); | |
66 | + depth++; | |
67 | + } else { | |
68 | + node = TREE_PARENT(node); | |
69 | + depth--; | |
70 | + } | |
71 | + } else { | |
72 | + /* | |
73 | + * if there are more elements to the left go there. | |
74 | + */ | |
75 | + previous = node; | |
76 | + node = TREE_LEFT(node); | |
77 | + depth++; | |
78 | + } | |
79 | + } | |
80 | + | |
81 | + *this = NULL; | |
82 | +} | |
83 | + | |
84 | +// vim: set ts=4 sw=4: | ... | ... |
src/tree/find.c
0 → 100644
1 | +/** | |
2 | + * \file | |
3 | + * | |
4 | + * \author Georg Hopp | |
5 | + * | |
6 | + * \copyright | |
7 | + * Copyright © 2012 Georg Hopp | |
8 | + * | |
9 | + * This program is free software: you can redistribute it and/or modify | |
10 | + * it under the terms of the GNU General Public License as published by | |
11 | + * the Free Software Foundation, either version 3 of the License, or | |
12 | + * (at your option) any later version. | |
13 | + * | |
14 | + * This program is distributed in the hope that it will be useful, | |
15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | + * GNU General Public License for more details. | |
18 | + * | |
19 | + * You should have received a copy of the GNU General Public License | |
20 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
21 | + */ | |
22 | + | |
23 | +#include "tree.h" | |
24 | + | |
25 | +void * | |
26 | +treeFind(Tree this, const void * search, TreeComp comp) | |
27 | +{ | |
28 | + while (NULL != this) { | |
29 | + int comparison = comp(this->data, search); | |
30 | + | |
31 | + if (0 < comparison) { | |
32 | + this = TREE_LEFT(this); | |
33 | + continue; | |
34 | + } | |
35 | + | |
36 | + if (0 > comparison) { | |
37 | + this = TREE_RIGHT(this); | |
38 | + continue; | |
39 | + } | |
40 | + | |
41 | + if (0 == comparison) { | |
42 | + break; | |
43 | + } | |
44 | + } | |
45 | + | |
46 | + return NULL != this ? this->data : NULL; | |
47 | +} | |
48 | + | |
49 | +// vim: set ts=4 sw=4: | ... | ... |
src/tree/inOrderSuccessor.c
0 → 100644
1 | +/** | |
2 | + * \file | |
3 | + * | |
4 | + * \author Georg Hopp | |
5 | + * | |
6 | + * \copyright | |
7 | + * Copyright © 2012 Georg Hopp | |
8 | + * | |
9 | + * This program is free software: you can redistribute it and/or modify | |
10 | + * it under the terms of the GNU General Public License as published by | |
11 | + * the Free Software Foundation, either version 3 of the License, or | |
12 | + * (at your option) any later version. | |
13 | + * | |
14 | + * This program is distributed in the hope that it will be useful, | |
15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | + * GNU General Public License for more details. | |
18 | + * | |
19 | + * You should have received a copy of the GNU General Public License | |
20 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
21 | + */ | |
22 | + | |
23 | +#include "tree.h" | |
24 | + | |
25 | +Tree | |
26 | +inOrderSuccessor(Tree this) | |
27 | +{ | |
28 | + this = TREE_RIGHT(this); | |
29 | + | |
30 | + while (NULL != TREE_LEFT(this)) { | |
31 | + this = TREE_LEFT(this); | |
32 | + } | |
33 | + | |
34 | + return this; | |
35 | +} | |
36 | + | |
37 | +// vim: set ts=4 sw=4: | ... | ... |
src/tree/insert.c
0 → 100644
1 | +/** | |
2 | + * \file | |
3 | + * | |
4 | + * \author Georg Hopp | |
5 | + * | |
6 | + * \copyright | |
7 | + * Copyright © 2012 Georg Hopp | |
8 | + * | |
9 | + * This program is free software: you can redistribute it and/or modify | |
10 | + * it under the terms of the GNU General Public License as published by | |
11 | + * the Free Software Foundation, either version 3 of the License, or | |
12 | + * (at your option) any later version. | |
13 | + * | |
14 | + * This program is distributed in the hope that it will be useful, | |
15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | + * GNU General Public License for more details. | |
18 | + * | |
19 | + * You should have received a copy of the GNU General Public License | |
20 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
21 | + */ | |
22 | + | |
23 | +#include "tree.h" | |
24 | + | |
25 | +void treeRotateLeft(Tree *, Tree); | |
26 | +void treeRotateRight(Tree *, Tree); | |
27 | + | |
28 | +void * | |
29 | +treeInsert(Tree * this, const void * search, TreeComp comp) | |
30 | +{ | |
31 | + Tree node = *this; | |
32 | + Tree new_node = NULL; | |
33 | + | |
34 | + /* | |
35 | + * insert the node or return the one in tree if comparison | |
36 | + * succeeds. | |
37 | + */ | |
38 | + if (NULL == node) { | |
39 | + /* | |
40 | + * if the root is NULL we simple add the element and set | |
41 | + * node to it. | |
42 | + */ | |
43 | + *this = node = new_node = new(Tree, search); | |
44 | + } else { | |
45 | + /* | |
46 | + * first search for it and if its found return the data | |
47 | + * and we are done... | |
48 | + */ | |
49 | + int comparison; | |
50 | + | |
51 | + while (NULL != node) { | |
52 | + comparison = comp(node->data, search); | |
53 | + | |
54 | + if (0 < comparison) { | |
55 | + if (NULL != TREE_LEFT(node)) { | |
56 | + node = TREE_LEFT(node); | |
57 | + continue; | |
58 | + } else { | |
59 | + break; | |
60 | + } | |
61 | + } | |
62 | + | |
63 | + if (0 > comparison) { | |
64 | + if (NULL != TREE_RIGHT(node)) { | |
65 | + node = TREE_RIGHT(node); | |
66 | + continue; | |
67 | + } else { | |
68 | + break; | |
69 | + } | |
70 | + } | |
71 | + | |
72 | + if (0 == comparison) { | |
73 | + return node->data; | |
74 | + } | |
75 | + } | |
76 | + | |
77 | + /* | |
78 | + * as we have not found it now add a new element. | |
79 | + */ | |
80 | + if (0 < comparison) { | |
81 | + node->left = new(Tree, search); | |
82 | + TREE_LEFT(node)->parent = node; | |
83 | + node = new_node = TREE_LEFT(node); | |
84 | + } else { | |
85 | + node->right = new(Tree, search); | |
86 | + TREE_RIGHT(node)->parent = node; | |
87 | + node = new_node = TREE_RIGHT(node); | |
88 | + } | |
89 | + } | |
90 | + | |
91 | + /* | |
92 | + * we expect node not to be NULL and pointing to our | |
93 | + * new node at this point...now rabalance the tree | |
94 | + */ | |
95 | + while (1) { | |
96 | + // case 1 | |
97 | + if (NULL == TREE_PARENT(node)) { | |
98 | + node->color = rbBlack; | |
99 | + break; | |
100 | + } | |
101 | + | |
102 | + // case 2 | |
103 | + if (rbBlack == TREE_PARENT(node)->color) { | |
104 | + break; | |
105 | + } | |
106 | + | |
107 | + // case 3 | |
108 | + if (NULL != TREE_UNCLE(node) && rbRed == TREE_UNCLE(node)->color) { | |
109 | + TREE_PARENT(node)->color = rbBlack; | |
110 | + TREE_UNCLE(node)->color = rbBlack; | |
111 | + TREE_GRANDPARENT(node)->color = rbRed; | |
112 | + | |
113 | + node = TREE_GRANDPARENT(node); | |
114 | + continue; | |
115 | + } | |
116 | + | |
117 | + // case 4 | |
118 | + if (node == TREE_PARENT(node)->right | |
119 | + && TREE_PARENT(node) == TREE_GRANDPARENT(node)->left) { | |
120 | + | |
121 | + //TREE_ROTATE_LEFT(this, TREE_PARENT(node)); | |
122 | + treeRotateLeft(this, TREE_PARENT(node)); | |
123 | + node = TREE_LEFT(node); | |
124 | + | |
125 | + } else if (node == TREE_PARENT(node)->left | |
126 | + && TREE_PARENT(node) == TREE_GRANDPARENT(node)->right) { | |
127 | + | |
128 | + //TREE_ROTATE_RIGHT(this, TREE_PARENT(node)); | |
129 | + treeRotateRight(this, TREE_PARENT(node)); | |
130 | + node = TREE_RIGHT(node); | |
131 | + | |
132 | + } | |
133 | + | |
134 | + // case 5 | |
135 | + TREE_PARENT(node)->color = rbBlack; | |
136 | + TREE_GRANDPARENT(node)->color = rbRed; | |
137 | + | |
138 | + if (node == TREE_PARENT(node)->left) { | |
139 | + //TREE_ROTATE_RIGHT(this, TREE_GRANDPARENT(node)); | |
140 | + treeRotateRight(this, TREE_GRANDPARENT(node)); | |
141 | + } else { | |
142 | + //TREE_ROTATE_LEFT(this, TREE_GRANDPARENT(node)); | |
143 | + treeRotateLeft(this, TREE_GRANDPARENT(node)); | |
144 | + } | |
145 | + | |
146 | + break; | |
147 | + } | |
148 | + | |
149 | + return new_node->data; | |
150 | +} | |
151 | + | |
152 | +// vim: set ts=4 sw=4: | ... | ... |
src/tree/rotateLeft.c
0 → 100644
1 | +/** | |
2 | + * \file | |
3 | + * | |
4 | + * \author Georg Hopp | |
5 | + * | |
6 | + * \copyright | |
7 | + * Copyright © 2012 Georg Hopp | |
8 | + * | |
9 | + * This program is free software: you can redistribute it and/or modify | |
10 | + * it under the terms of the GNU General Public License as published by | |
11 | + * the Free Software Foundation, either version 3 of the License, or | |
12 | + * (at your option) any later version. | |
13 | + * | |
14 | + * This program is distributed in the hope that it will be useful, | |
15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | + * GNU General Public License for more details. | |
18 | + * | |
19 | + * You should have received a copy of the GNU General Public License | |
20 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
21 | + */ | |
22 | + | |
23 | +#include "tree.h" | |
24 | + | |
25 | +void | |
26 | +treeRotateLeft(Tree * this, Tree node) | |
27 | +{ | |
28 | + Tree rightChild = TREE_RIGHT(node); | |
29 | + Tree rcLeftSub = TREE_RIGHT_LEFT(node); | |
30 | + | |
31 | + rightChild->left = node; | |
32 | + rightChild->parent = TREE_PARENT(node); | |
33 | + node->right = rcLeftSub; | |
34 | + if (NULL != rcLeftSub) { | |
35 | + rcLeftSub->parent = node; | |
36 | + } | |
37 | + | |
38 | + if (NULL != TREE_PARENT(node)) { | |
39 | + if (TREE_PARENT(node)->left == node) { | |
40 | + TREE_PARENT(node)->left = rightChild; | |
41 | + } else { | |
42 | + TREE_PARENT(node)->right = rightChild; | |
43 | + } | |
44 | + } else { | |
45 | + *this = rightChild; | |
46 | + } | |
47 | + | |
48 | + node->parent = rightChild; | |
49 | +} | |
50 | + | |
51 | +// vim: set ts=4 sw=4: | ... | ... |
src/tree/rotateRight.c
0 → 100644
1 | +/** | |
2 | + * \file | |
3 | + * | |
4 | + * \author Georg Hopp | |
5 | + * | |
6 | + * \copyright | |
7 | + * Copyright © 2012 Georg Hopp | |
8 | + * | |
9 | + * This program is free software: you can redistribute it and/or modify | |
10 | + * it under the terms of the GNU General Public License as published by | |
11 | + * the Free Software Foundation, either version 3 of the License, or | |
12 | + * (at your option) any later version. | |
13 | + * | |
14 | + * This program is distributed in the hope that it will be useful, | |
15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | + * GNU General Public License for more details. | |
18 | + * | |
19 | + * You should have received a copy of the GNU General Public License | |
20 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
21 | + */ | |
22 | + | |
23 | +#include "tree.h" | |
24 | + | |
25 | +void | |
26 | +treeRotateRight(Tree * this, Tree node) | |
27 | +{ | |
28 | + Tree leftChild = TREE_LEFT(node); | |
29 | + Tree lcRightSub = TREE_LEFT_RIGHT(node); | |
30 | + | |
31 | + leftChild->right = node; | |
32 | + leftChild->parent = TREE_PARENT(node); | |
33 | + node->left = lcRightSub; | |
34 | + if (NULL != lcRightSub) { | |
35 | + lcRightSub->parent = node; | |
36 | + } | |
37 | + | |
38 | + if (NULL != TREE_PARENT(node)) { | |
39 | + if (TREE_PARENT(node)->left == node) { | |
40 | + TREE_PARENT(node)->left = leftChild; | |
41 | + } else { | |
42 | + TREE_PARENT(node)->right = leftChild; | |
43 | + } | |
44 | + } else { | |
45 | + *this = leftChild; | |
46 | + } | |
47 | + | |
48 | + node->parent = leftChild; | |
49 | +} | |
50 | + | |
51 | +// vim: set ts=4 sw=4: | ... | ... |
src/tree/tree.c
0 → 100644
1 | +/** | |
2 | + * \file | |
3 | + * | |
4 | + * \author Georg Hopp | |
5 | + * | |
6 | + * \copyright | |
7 | + * Copyright © 2012 Georg Hopp | |
8 | + * | |
9 | + * This program is free software: you can redistribute it and/or modify | |
10 | + * it under the terms of the GNU General Public License as published by | |
11 | + * the Free Software Foundation, either version 3 of the License, or | |
12 | + * (at your option) any later version. | |
13 | + * | |
14 | + * This program is distributed in the hope that it will be useful, | |
15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | + * GNU General Public License for more details. | |
18 | + * | |
19 | + * You should have received a copy of the GNU General Public License | |
20 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
21 | + */ | |
22 | + | |
23 | +#define _GNU_SOURCE | |
24 | + | |
25 | +#include <stdarg.h> | |
26 | + | |
27 | +#include "tree.h" | |
28 | +#include "class.h" | |
29 | + | |
30 | +static | |
31 | +int | |
32 | +treeCtor(void * _this, va_list * params) | |
33 | +{ | |
34 | + Tree this = _this; | |
35 | + | |
36 | + this->data = va_arg(*params, void *); | |
37 | + this->color = rbRed; | |
38 | + this->parent = NULL; | |
39 | + this->left = NULL; | |
40 | + this->right = NULL; | |
41 | + | |
42 | + return 0; | |
43 | +} | |
44 | + | |
45 | +static | |
46 | +void | |
47 | +treeDtor(void * _this) | |
48 | +{ | |
49 | +} | |
50 | + | |
51 | +INIT_IFACE(Class, treeCtor, treeDtor, NULL); | |
52 | +CREATE_CLASS(Tree, NULL, IFACE(Class)); | |
53 | + | |
54 | +// vim: set ts=4 sw=4: | ... | ... |
src/tree/walk.c
0 → 100644
1 | +/** | |
2 | + * \file | |
3 | + * | |
4 | + * \author Georg Hopp | |
5 | + * | |
6 | + * \copyright | |
7 | + * Copyright © 2012 Georg Hopp | |
8 | + * | |
9 | + * This program is free software: you can redistribute it and/or modify | |
10 | + * it under the terms of the GNU General Public License as published by | |
11 | + * the Free Software Foundation, either version 3 of the License, or | |
12 | + * (at your option) any later version. | |
13 | + * | |
14 | + * This program is distributed in the hope that it will be useful, | |
15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | + * GNU General Public License for more details. | |
18 | + * | |
19 | + * You should have received a copy of the GNU General Public License | |
20 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
21 | + */ | |
22 | + | |
23 | +#include "tree.h" | |
24 | + | |
25 | +void | |
26 | +treeWalk(Tree this, TreeAction action) | |
27 | +{ | |
28 | + Tree previous = this; | |
29 | + Tree node = this; | |
30 | + int depth = 1; | |
31 | + | |
32 | + while (NULL != node) { | |
33 | + if (previous == TREE_RIGHT(node)) { | |
34 | + previous = node; | |
35 | + node = node->parent; | |
36 | + depth--; | |
37 | + continue; | |
38 | + } | |
39 | + | |
40 | + if (NULL == TREE_LEFT(node) || previous == TREE_LEFT(node)) { | |
41 | + action(node->data, depth); | |
42 | + previous = node; | |
43 | + | |
44 | + if (NULL != TREE_RIGHT(node)) { | |
45 | + node = TREE_RIGHT(node); | |
46 | + depth++; | |
47 | + } else { | |
48 | + node = TREE_PARENT(node); | |
49 | + depth--; | |
50 | + } | |
51 | + } else { | |
52 | + previous = node; | |
53 | + node = TREE_LEFT(node); | |
54 | + depth++; | |
55 | + } | |
56 | + } | |
57 | +} | |
58 | + | |
59 | +// vim: set ts=4 sw=4: | ... | ... |
... | ... | @@ -54,14 +54,12 @@ |
54 | 54 | #include <unistd.h> |
55 | 55 | |
56 | 56 | #include "utils/memory.h" |
57 | +#include "tree.h" | |
57 | 58 | |
58 | 59 | |
59 | 60 | #define PAGE_SIZE = 32 |
60 | 61 | |
61 | 62 | |
62 | -enum rbColor {rbBlack=1, rbRed=2}; | |
63 | - | |
64 | - | |
65 | 63 | struct memSegment |
66 | 64 | { |
67 | 65 | size_t size; |
... | ... | @@ -394,8 +392,6 @@ findInOrderSuccessor(struct memSegment * tree) |
394 | 392 | return node; |
395 | 393 | } |
396 | 394 | |
397 | -struct memSegment * deleteOneChild(struct memSegment **, struct memSegment *); | |
398 | - | |
399 | 395 | struct memSegment * |
400 | 396 | deleteElement(struct memSegment ** tree, struct memSegment * element) |
401 | 397 | { |
... | ... | @@ -619,8 +615,6 @@ deleteElement(struct memSegment ** tree, struct memSegment * element) |
619 | 615 | break; |
620 | 616 | } |
621 | 617 | |
622 | - //deleteOneChild(tree, node); | |
623 | - | |
624 | 618 | return del_node; |
625 | 619 | } |
626 | 620 | ... | ... |
Please
register
or
login
to post a comment