removed listbag added tree bag
[wmaker-crm.git] / WINGs / bagtree.c
blob0f330489beb6e95325d3808432a6534cc69ef715
5 #include <stdlib.h>
6 #include <string.h>
8 #include "WUtil.h"
11 typedef struct W_Node {
12 struct W_Node *parent;
13 struct W_Node *left;
14 struct W_Node *right;
15 int color;
17 void *data;
18 int index;
19 } W_Node;
22 typedef struct W_TreeBag {
23 W_Node *root;
25 W_Node *nil; /* sentinel */
27 int count;
28 } W_TreeBag;
32 static int getItemCount(WMBag *self);
33 static int appendBag(WMBag *self, WMBag *bag);
34 static int putInBag(WMBag *self, void *item);
35 static int insertInBag(WMBag *self, int index, void *item);
36 static int removeFromBag(WMBag *bag, void *item);
37 static int deleteFromBag(WMBag *bag, int index);
38 static void *getFromBag(WMBag *bag, int index);
39 static int countInBag(WMBag *bag, void *item);
40 static int firstInBag(WMBag *bag, void *item);
41 static void *replaceInBag(WMBag *bag, int index, void *item);
42 static int sortBag(WMBag *bag, int (*comparer)(const void*, const void*));
43 static void emptyBag(WMBag *bag);
44 static void freeBag(WMBag *bag);
45 static void mapBag(WMBag *bag, void (*function)(void*, void*), void *data);
46 static int findInBag(WMBag *bag, int (*match)(void*));;
47 static void *first(WMBag *bag, WMBagIterator *ptr);
48 static void *last(WMBag *bag, WMBagIterator *ptr);
49 static void *next(WMBag *bag, WMBagIterator *ptr);
50 static void *previous(WMBag *bag, WMBagIterator *ptr);
51 static void *iteratorAtIndex(WMBag *bag, int index, WMBagIterator *ptr);
52 static int indexForIterator(WMBag *bag, WMBagIterator ptr);
55 static W_BagFunctions bagFunctions = {
56 getItemCount,
57 appendBag,
58 putInBag,
59 insertInBag,
60 removeFromBag,
61 deleteFromBag,
62 getFromBag,
63 firstInBag,
64 countInBag,
65 replaceInBag,
66 sortBag,
67 emptyBag,
68 freeBag,
69 mapBag,
70 findInBag,
71 first,
72 last,
73 next,
74 previous,
75 iteratorAtIndex,
76 indexForIterator
82 #define IS_LEFT(node) (node == node->parent->left)
83 #define IS_RIGHT(node) (node == node->parent->right)
87 static void leftRotate(W_TreeBag *tree, W_Node *node)
89 W_Node *node2;
91 node2 = node->right;
92 node->right = node2->left;
94 node2->left->parent = node;
96 node2->parent = node->parent;
98 if (node->parent == tree->nil) {
99 tree->root = node2;
100 } else {
101 if (IS_LEFT(node)) {
102 node->parent->left = node2;
103 } else {
104 node->parent->right = node2;
107 node2->left = node;
108 node->parent = node2;
113 static void rightRotate(W_TreeBag *tree, W_Node *node)
115 W_Node *node2;
117 node2 = node->left;
118 node->left = node2->right;
120 node2->right->parent = node;
122 node2->parent = node->parent;
124 if (node->parent == tree->nil) {
125 tree->root = node2;
126 } else {
127 if (IS_LEFT(node)) {
128 node->parent->left = node2;
129 } else {
130 node->parent->right = node2;
133 node2->right = node;
134 node->parent = node2;
139 static void treeInsert(W_TreeBag *tree, W_Node *node)
141 W_Node *y = tree->nil;
142 W_Node *x = tree->root;
144 while (x != tree->nil) {
145 y = x;
146 if (node->index < x->index)
147 x = x->left;
148 else
149 x = x->right;
151 node->parent = y;
152 if (y == tree->nil)
153 tree->root = node;
154 else if (node->index < y->index)
155 y->left = node;
156 else
157 y->right = node;
161 static void rbTreeInsert(W_TreeBag *tree, W_Node *node)
163 W_Node *y;
165 treeInsert(tree, node);
167 node->color = 'R';
169 while (node != tree->root && node->parent->color == 'R') {
170 if (IS_LEFT(node->parent)) {
171 y = node->parent->parent->right;
173 if (y->color == 'R') {
175 node->parent->color = 'B';
176 y->color = 'B';
177 node->parent->parent->color = 'R';
178 node = node->parent->parent;
180 } else {
181 if (IS_RIGHT(node)) {
182 node = node->parent;
183 leftRotate(tree, node);
185 node->parent->color = 'B';
186 node->parent->parent->color = 'R';
187 rightRotate(tree, node->parent->parent);
189 } else {
190 y = node->parent->parent->left;
192 if (y->color == 'R') {
194 node->parent->color = 'B';
195 y->color = 'B';
196 node->parent->parent->color = 'R';
197 node = node->parent->parent;
199 } else {
200 if (IS_LEFT(node)) {
201 node = node->parent;
202 rightRotate(tree, node);
204 node->parent->color = 'B';
205 node->parent->parent->color = 'R';
206 leftRotate(tree, node->parent->parent);
210 tree->root->color = 'B';
215 static void rbDeleteFixup(W_TreeBag *tree, W_Node *node)
217 W_Node *w;
219 while (node != tree->root && node->color == 'B') {
220 if (IS_LEFT(node)) {
221 w = node->parent->right;
222 if (w->color == 'R') {
223 w->color = 'B';
224 node->parent->color = 'R';
225 leftRotate(tree, node->parent);
226 w = node->parent->right;
228 if (w->left->color == 'B' && w->right->color == 'B') {
229 w->color = 'R';
230 node = node->parent;
231 } else {
232 if (w->right->color == 'B') {
233 w->left->color = 'B';
234 w->color = 'R';
235 rightRotate(tree, w);
236 w = node->parent->right;
238 w->color = node->parent->color;
239 node->parent->color = 'B';
240 w->right->color = 'B';
241 leftRotate(tree, node->parent);
242 node = tree->root;
244 } else {
245 w = node->parent->left;
246 if (w->color == 'R') {
247 w->color = 'B';
248 node->parent->color = 'R';
249 leftRotate(tree, node->parent);
250 w = node->parent->left;
252 if (w->left->color == 'B' && w->right->color == 'B') {
253 w->color = 'R';
254 node = node->parent;
255 } else {
256 if (w->left->color == 'B') {
257 w->right->color = 'B';
258 w->color = 'R';
259 rightRotate(tree, w);
260 w = node->parent->left;
262 w->color = node->parent->color;
263 node->parent->color = 'B';
264 w->left->color = 'B';
265 leftRotate(tree, node->parent);
266 node = tree->root;
270 node->color = 'B';
274 static W_Node *treeMinimum(W_Node *node, W_Node *nil)
276 while (node->left != nil)
277 node = node->left;
278 return node;
282 static W_Node *treeMaximum(W_Node *node, W_Node *nil)
284 while (node->right != nil)
285 node = node->right;
286 return node;
290 static W_Node *treeSuccessor(W_Node *node, W_Node *nil)
292 W_Node *y;
294 if (node->right != nil) {
295 return treeMinimum(node->right, nil);
297 y = node->parent;
298 while (y != nil && node == y->right) {
299 node = y;
300 y = y->parent;
302 return y;
306 static W_Node *treePredecessor(W_Node *node, W_Node *nil)
308 W_Node *y;
310 if (node->left != nil) {
311 return treeMaximum(node->left, nil);
313 y = node->parent;
314 while (y != nil && node == y->left) {
315 node = y;
316 y = y->parent;
318 return y;
322 static W_Node *rbTreeDelete(W_TreeBag *tree, W_Node *node)
324 W_Node *nil = tree->nil;
325 W_Node *x, *y;
327 if (node->left == nil || node->right == nil) {
328 y = node;
329 } else {
330 y = treeSuccessor(node, nil);
333 if (y->left != nil) {
334 x = y->left;
335 } else {
336 x = y->right;
339 x->parent = y->parent;
341 if (y->parent == nil) {
342 tree->root = x;
343 } else {
344 if (IS_LEFT(y)) {
345 y->parent->left = x;
346 } else {
347 y->parent->right = x;
350 if (y != node) {
351 node->index = y->index;
352 node->data = y->data;
354 if (y->color == 'B') {
355 rbDeleteFixup(tree, x);
358 return y;
363 static W_Node *treeSearch(W_Node *root, W_Node *nil, int index)
365 if (root == nil || root->index == index) {
366 return root;
369 if (index < root->index) {
370 return treeSearch(root->left, nil, index);
371 } else {
372 return treeSearch(root->right, nil, index);
377 static W_Node *treeFind(W_Node *root, W_Node *nil, void *data)
379 W_Node *tmp;
381 if (root == nil || root->data == data)
382 return root;
384 tmp = treeFind(root->left, nil, data);
385 if (tmp != nil)
386 return tmp;
388 tmp = treeFind(root->right, nil, data);
390 return tmp;
397 #if 0
398 static char buf[512];
400 static void printNodes(W_Node *node, W_Node *nil, int depth)
402 if (node == nil) {
403 return;
406 printNodes(node->left, nil, depth+1);
408 memset(buf, ' ', depth*2);
409 buf[depth*2] = 0;
410 if (IS_LEFT(node))
411 printf("%s/(%2i\n", buf, node->index);
412 else
413 printf("%s\\(%2i\n", buf, node->index);
415 printNodes(node->right, nil, depth+1);
419 void PrintTree(WMBag *bag)
421 W_TreeBag *tree = (W_TreeBag*)bag->data;
423 printNodes(tree->root, tree->nil, 0);
425 #endif
430 #define SELF ((W_TreeBag*)self->data)
432 WMBag *WMCreateTreeBag(void)
434 return WMCreateTreeBagWithDestructor(NULL);
438 WMBag *WMCreateTreeBagWithDestructor(void (*destructor)(void*))
440 WMBag *bag;
441 W_TreeBag *tree;
443 bag = wmalloc(sizeof(WMBag));
445 bag->data = tree = wmalloc(sizeof(W_TreeBag));
446 memset(tree, 0, sizeof(W_TreeBag));
448 tree->nil = wmalloc(sizeof(W_Node));
449 memset(tree->nil, 0, sizeof(W_Node));
450 tree->nil->left = tree->nil->right = tree->nil->parent = tree->nil;
451 tree->nil->index = WBNotFound;
453 tree->root = tree->nil;
455 bag->destructor = destructor;
457 bag->func = bagFunctions;
459 return bag;
463 static int getItemCount(WMBag *self)
465 return SELF->count;
469 static int appendBag(WMBag *self, WMBag *bag)
471 WMBagIterator ptr;
472 void *data;
474 for (data = first(bag, &ptr); data != NULL; data = next(bag, &ptr)) {
475 if (!putInBag(self, data))
476 return 0;
479 return 1;
483 static int putInBag(WMBag *self, void *item)
485 W_Node *ptr;
487 ptr = wmalloc(sizeof(W_Node));
489 ptr->data = item;
490 ptr->index = SELF->count;
491 ptr->left = SELF->nil;
492 ptr->right = SELF->nil;
493 ptr->parent = SELF->nil;
495 rbTreeInsert(SELF, ptr);
497 SELF->count++;
499 return 1;
503 static int insertInBag(WMBag *self, int index, void *item)
505 W_Node *ptr;
507 ptr = wmalloc(sizeof(W_Node));
509 ptr->data = item;
510 ptr->index = index;
511 ptr->left = SELF->nil;
512 ptr->right = SELF->nil;
513 ptr->parent = SELF->nil;
515 rbTreeInsert(SELF, ptr);
517 while ((ptr = treeSuccessor(ptr, SELF->nil))) {
518 ptr->index++;
522 SELF->count++;
524 return 1;
529 static int removeFromBag(WMBag *self, void *item)
531 W_Node *ptr = treeFind(SELF->root, SELF->nil, item);
533 if (ptr != SELF->nil) {
535 SELF->count--;
537 ptr = rbTreeDelete(SELF, ptr);
538 free(ptr);
540 return 1;
541 } else {
542 return 0;
547 static int deleteFromBag(WMBag *self, int index)
549 W_Node *ptr = treeSearch(SELF->root, SELF->nil, index);
551 if (ptr != SELF->nil) {
553 SELF->count--;
555 ptr = rbTreeDelete(SELF, ptr);
556 free(ptr);
558 return 1;
559 } else {
560 return 0;
565 static void *getFromBag(WMBag *self, int index)
567 W_Node *node;
569 if (SELF->count>0)
570 assert(SELF->root != SELF->nil);
572 node = treeSearch(SELF->root, SELF->nil, index);
573 if (node != SELF->nil)
574 return node->data;
575 else
576 return NULL;
581 static int firstInBag(WMBag *self, void *item)
583 W_Node *node;
585 node = treeFind(SELF->root, SELF->nil, item);
586 if (node != SELF->nil)
587 return node->index;
588 else
589 return WBNotFound;
594 static int treeCount(W_Node *root, W_Node *nil, void *item)
596 int count = 0;
598 if (root == nil)
599 return 0;
601 if (root->data == item)
602 count++;
604 if (root->left != nil)
605 count += treeCount(root->left, nil, item);
607 if (root->right != nil)
608 count += treeCount(root->right, nil, item);
610 return count;
615 static int countInBag(WMBag *self, void *item)
617 return treeCount(SELF->root, SELF->nil, item);
621 static void *replaceInBag(WMBag *self, int index, void *item)
623 W_Node *ptr = treeSearch(SELF->root, SELF->nil, index);
624 void *old = NULL;
626 if (item == NULL) {
627 SELF->count--;
629 ptr = rbTreeDelete(SELF, ptr);
630 free(ptr);
631 } else if (ptr != SELF->nil) {
632 old = ptr->data;
633 ptr->data = item;
634 } else {
635 insertInBag(self, index, item);
638 return old;
643 static int sortBag(WMBag *self, int (*comparer)(const void*, const void*))
645 assert(0&&"not implemented");
647 return 0;
653 static void deleteTree(WMBag *self, W_Node *node)
655 if (node == SELF->nil)
656 return;
658 deleteTree(self, node->left);
660 if (self->destructor)
661 self->destructor(node->data);
663 deleteTree(self, node->right);
665 free(node);
669 static void emptyBag(WMBag *self)
671 deleteTree(self, SELF->root);
672 SELF->root = SELF->nil;
673 SELF->count = 0;
677 static void freeBag(WMBag *self)
679 emptyBag(self);
681 free(self);
686 static void mapTree(W_TreeBag *tree, W_Node *node,
687 void (*function)(void*, void*), void *data)
689 if (node == tree->nil)
690 return;
692 mapTree(tree, node->left, function, data);
694 (*function)(node->data, data);
696 mapTree(tree, node->right, function, data);
700 static void mapBag(WMBag *self, void (*function)(void*, void*), void *data)
702 mapTree(SELF, SELF->root, function, data);
707 static int findInTree(W_TreeBag *tree, W_Node *node, int (*function)(void*))
709 int index;
711 if (node == tree->nil)
712 return WBNotFound;
714 index = findInTree(tree, node->left, function);
715 if (index != WBNotFound)
716 return index;
718 if ((*function)(node->data)) {
719 return node->index;
722 return findInTree(tree, node->right, function);
726 static int findInBag(WMBag *self, int (*match)(void*))
728 return findInTree(SELF, SELF->root, match);
734 static void *first(WMBag *self, WMBagIterator *ptr)
736 W_Node *node;
738 node = treeMinimum(SELF->root, SELF->nil);
740 if (node == SELF->nil) {
741 *ptr = NULL;
743 return NULL;
744 } else {
745 *ptr = node;
747 return node->data;
753 static void *last(WMBag *self, WMBagIterator *ptr)
756 W_Node *node;
758 node = treeMaximum(SELF->root, SELF->nil);
760 if (node == SELF->nil) {
761 *ptr = NULL;
763 return NULL;
764 } else {
765 *ptr = node;
767 return node->data;
773 static void *next(WMBag *self, WMBagIterator *ptr)
775 W_Node *node;
777 if (*ptr == NULL)
778 return NULL;
780 node = treeSuccessor(*ptr, SELF->nil);
782 if (node == SELF->nil) {
783 *ptr = NULL;
785 return NULL;
786 } else {
787 *ptr = node;
789 return node->data;
795 static void *previous(WMBag *self, WMBagIterator *ptr)
797 W_Node *node;
799 if (*ptr == NULL)
800 return NULL;
802 node = treePredecessor(*ptr, SELF->nil);
805 if (node == SELF->nil) {
806 *ptr = NULL;
808 return NULL;
809 } else {
810 *ptr = node;
812 return node->data;
818 static void *iteratorAtIndex(WMBag *self, int index, WMBagIterator *ptr)
820 W_Node *node;
822 node = treeSearch(SELF->root, SELF->nil, index);
824 if (node == SELF->nil) {
825 *ptr = NULL;
826 return NULL;
827 } else {
828 *ptr = node;
829 return node->data;
834 static int indexForIterator(WMBag *bag, WMBagIterator ptr)
836 return ((W_Node*)ptr)->index;