1 /*******************************************************************************
2 * Copyright (c) 2009, 2020 IBM Corp.
3 *
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v2.0
6 * and Eclipse Distribution License v1.0 which accompany this distribution.
7 *
8 * The Eclipse Public License is available at
9 * https://www.eclipse.org/legal/epl-2.0/
10 * and the Eclipse Distribution License is available at
11 * http://www.eclipse.org/org/documents/edl-v10.php.
12 *
13 * Contributors:
14 * Ian Craggs - initial implementation and documentation
15 *******************************************************************************/
16
17 /** @file
18 * \brief functions which apply to tree structures.
19 *
20 * These trees can hold data of any sort, pointed to by the content pointer of the
21 * Node structure.
22 * */
23
24 #define TREE_C /* so that malloc/free/realloc aren't redefined by Heap.h */
25
26 #include "Tree.h"
27
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31
32 #include "Heap.h"
33
34
35 int isRed(Node* aNode);
36 int isBlack(Node* aNode);
37 /*int TreeWalk(Node* curnode, int depth);*/
38 /*int TreeMaxDepth(Tree *aTree);*/
39 void TreeRotate(Tree* aTree, Node* curnode, int direction, int index);
40 Node* TreeBAASub(Tree* aTree, Node* curnode, int which, int index);
41 void TreeBalanceAfterAdd(Tree* aTree, Node* curnode, int index);
42 void* TreeAddByIndex(Tree* aTree, void* content, size_t size, int index);
43 Node* TreeFindIndex1(Tree* aTree, void* key, int index, int value);
44 Node* TreeFindContentIndex(Tree* aTree, void* key, int index);
45 Node* TreeMinimum(Node* curnode);
46 Node* TreeSuccessor(Node* curnode);
47 Node* TreeNextElementIndex(Tree* aTree, Node* curnode, int index);
48 Node* TreeBARSub(Tree* aTree, Node* curnode, int which, int index);
49 void TreeBalanceAfterRemove(Tree* aTree, Node* curnode, int index);
50 void* TreeRemoveIndex(Tree* aTree, void* content, int index);
51
52
TreeInitializeNoMalloc(Tree * aTree,int (* compare)(void *,void *,int))53 void TreeInitializeNoMalloc(Tree* aTree, int(*compare)(void*, void*, int))
54 {
55 memset(aTree, '\0', sizeof(Tree));
56 aTree->heap_tracking = 1;
57 aTree->index[0].compare = compare;
58 aTree->indexes = 1;
59 }
60
61 /**
62 * Allocates and initializes a new tree structure.
63 * @return a pointer to the new tree structure
64 */
TreeInitialize(int (* compare)(void *,void *,int))65 Tree* TreeInitialize(int(*compare)(void*, void*, int))
66 {
67 #if defined(UNIT_TESTS) || defined(NO_HEAP_TRACKING)
68 Tree* newt = malloc(sizeof(Tree));
69 #else
70 Tree* newt = mymalloc(__FILE__, __LINE__, sizeof(Tree));
71 #endif
72 if (newt)
73 TreeInitializeNoMalloc(newt, compare);
74 return newt;
75 }
76
77
TreeAddIndex(Tree * aTree,int (* compare)(void *,void *,int))78 void TreeAddIndex(Tree* aTree, int(*compare)(void*, void*, int))
79 {
80 aTree->index[aTree->indexes].compare = compare;
81 ++(aTree->indexes);
82 }
83
84
TreeFree(Tree * aTree)85 void TreeFree(Tree* aTree)
86 {
87 #if defined(UNIT_TESTS) || defined(NO_HEAP_TRACKING)
88 free(aTree);
89 #else
90 (aTree->heap_tracking) ? myfree(__FILE__, __LINE__, aTree) : free(aTree);
91 #endif
92 }
93
94
95 #define LEFT 0
96 #define RIGHT 1
97 #if !defined(max)
98 #define max(a, b) (a > b) ? a : b;
99 #endif
100
101
102
isRed(Node * aNode)103 int isRed(Node* aNode)
104 {
105 return (aNode != NULL) && (aNode->red);
106 }
107
108
isBlack(Node * aNode)109 int isBlack(Node* aNode)
110 {
111 return (aNode == NULL) || (aNode->red == 0);
112 }
113
114 #if 0
115 int TreeWalk(Node* curnode, int depth)
116 {
117 if (curnode)
118 {
119 int left = TreeWalk(curnode->child[LEFT], depth+1);
120 int right = TreeWalk(curnode->child[RIGHT], depth+1);
121 depth = max(left, right);
122 if (curnode->red)
123 {
124 /*if (isRed(curnode->child[LEFT]) || isRed(curnode->child[RIGHT]))
125 {
126 printf("red/black tree violation %p\n", curnode->content);
127 exit(-99);
128 }*/;
129 }
130 }
131 return depth;
132 }
133
134
135 int TreeMaxDepth(Tree *aTree)
136 {
137 int rc = TreeWalk(aTree->index[0].root, 0);
138 /*if (aTree->root->red)
139 {
140 printf("root node should not be red %p\n", aTree->root->content);
141 exit(-99);
142 }*/
143 return rc;
144 }
145 #endif
146
TreeRotate(Tree * aTree,Node * curnode,int direction,int index)147 void TreeRotate(Tree* aTree, Node* curnode, int direction, int index)
148 {
149 Node* other = curnode->child[!direction];
150
151 curnode->child[!direction] = other->child[direction];
152 if (other->child[direction] != NULL)
153 other->child[direction]->parent = curnode;
154 other->parent = curnode->parent;
155 if (curnode->parent == NULL)
156 aTree->index[index].root = other;
157 else if (curnode == curnode->parent->child[direction])
158 curnode->parent->child[direction] = other;
159 else
160 curnode->parent->child[!direction] = other;
161 other->child[direction] = curnode;
162 curnode->parent = other;
163 }
164
165
TreeBAASub(Tree * aTree,Node * curnode,int which,int index)166 Node* TreeBAASub(Tree* aTree, Node* curnode, int which, int index)
167 {
168 Node* uncle = curnode->parent->parent->child[which];
169
170 if (isRed(uncle))
171 {
172 curnode->parent->red = uncle->red = 0;
173 curnode = curnode->parent->parent;
174 curnode->red = 1;
175 }
176 else
177 {
178 if (curnode == curnode->parent->child[which])
179 {
180 curnode = curnode->parent;
181 TreeRotate(aTree, curnode, !which, index);
182 }
183 curnode->parent->red = 0;
184 curnode->parent->parent->red = 1;
185 TreeRotate(aTree, curnode->parent->parent, which, index);
186 }
187 return curnode;
188 }
189
190
TreeBalanceAfterAdd(Tree * aTree,Node * curnode,int index)191 void TreeBalanceAfterAdd(Tree* aTree, Node* curnode, int index)
192 {
193 while (curnode && isRed(curnode->parent) && curnode->parent->parent)
194 {
195 if (curnode->parent == curnode->parent->parent->child[LEFT])
196 curnode = TreeBAASub(aTree, curnode, RIGHT, index);
197 else
198 curnode = TreeBAASub(aTree, curnode, LEFT, index);
199 }
200 aTree->index[index].root->red = 0;
201 }
202
203
204 /**
205 * Add an item to a tree
206 * @param aTree the list to which the item is to be added
207 * @param content the list item content itself
208 * @param size the size of the element
209 */
TreeAddByIndex(Tree * aTree,void * content,size_t size,int index)210 void* TreeAddByIndex(Tree* aTree, void* content, size_t size, int index)
211 {
212 Node* curparent = NULL;
213 Node* curnode = aTree->index[index].root;
214 Node* newel = NULL;
215 int left = 0;
216 int result = 1;
217 void* rc = NULL;
218
219 while (curnode)
220 {
221 result = aTree->index[index].compare(curnode->content, content, 1);
222 left = (result > 0);
223 if (result == 0)
224 break;
225 else
226 {
227 curparent = curnode;
228 curnode = curnode->child[left];
229 }
230 }
231
232 if (result == 0)
233 {
234 if (aTree->allow_duplicates)
235 goto exit; /* exit(-99); */
236 else
237 {
238 newel = curnode;
239 if (index == 0)
240 aTree->size += (size - curnode->size);
241 }
242 }
243 else
244 {
245 #if defined(UNIT_TESTS) || defined(NO_HEAP_TRACKING)
246 newel = malloc(sizeof(Node));
247 #else
248 newel = (aTree->heap_tracking) ? mymalloc(__FILE__, __LINE__, sizeof(Node)) : malloc(sizeof(Node));
249 #endif
250 if (newel == NULL)
251 goto exit;
252 memset(newel, '\0', sizeof(Node));
253 if (curparent)
254 curparent->child[left] = newel;
255 else
256 aTree->index[index].root = newel;
257 newel->parent = curparent;
258 newel->red = 1;
259 if (index == 0)
260 {
261 ++(aTree->count);
262 aTree->size += size;
263 }
264 }
265 newel->content = content;
266 newel->size = size;
267 rc = newel->content;
268 TreeBalanceAfterAdd(aTree, newel, index);
269 exit:
270 return rc;
271 }
272
273
TreeAdd(Tree * aTree,void * content,size_t size)274 void* TreeAdd(Tree* aTree, void* content, size_t size)
275 {
276 void* rc = NULL;
277 int i;
278
279 for (i = 0; i < aTree->indexes; ++i)
280 rc = TreeAddByIndex(aTree, content, size, i);
281
282 return rc;
283 }
284
285
TreeFindIndex1(Tree * aTree,void * key,int index,int value)286 Node* TreeFindIndex1(Tree* aTree, void* key, int index, int value)
287 {
288 int result = 0;
289 Node* curnode = aTree->index[index].root;
290
291 while (curnode)
292 {
293 result = aTree->index[index].compare(curnode->content, key, value);
294 if (result == 0)
295 break;
296 else
297 curnode = curnode->child[result > 0];
298 }
299 return curnode;
300 }
301
302
TreeFindIndex(Tree * aTree,void * key,int index)303 Node* TreeFindIndex(Tree* aTree, void* key, int index)
304 {
305 return TreeFindIndex1(aTree, key, index, 0);
306 }
307
308
TreeFindContentIndex(Tree * aTree,void * key,int index)309 Node* TreeFindContentIndex(Tree* aTree, void* key, int index)
310 {
311 return TreeFindIndex1(aTree, key, index, 1);
312 }
313
314
TreeFind(Tree * aTree,void * key)315 Node* TreeFind(Tree* aTree, void* key)
316 {
317 return TreeFindIndex(aTree, key, 0);
318 }
319
320
TreeMinimum(Node * curnode)321 Node* TreeMinimum(Node* curnode)
322 {
323 if (curnode)
324 while (curnode->child[LEFT])
325 curnode = curnode->child[LEFT];
326 return curnode;
327 }
328
329
TreeSuccessor(Node * curnode)330 Node* TreeSuccessor(Node* curnode)
331 {
332 if (curnode->child[RIGHT])
333 curnode = TreeMinimum(curnode->child[RIGHT]);
334 else
335 {
336 Node* curparent = curnode->parent;
337 while (curparent && curnode == curparent->child[RIGHT])
338 {
339 curnode = curparent;
340 curparent = curparent->parent;
341 }
342 curnode = curparent;
343 }
344 return curnode;
345 }
346
347
TreeNextElementIndex(Tree * aTree,Node * curnode,int index)348 Node* TreeNextElementIndex(Tree* aTree, Node* curnode, int index)
349 {
350 if (curnode == NULL)
351 curnode = TreeMinimum(aTree->index[index].root);
352 else
353 curnode = TreeSuccessor(curnode);
354 return curnode;
355 }
356
357
TreeNextElement(Tree * aTree,Node * curnode)358 Node* TreeNextElement(Tree* aTree, Node* curnode)
359 {
360 return TreeNextElementIndex(aTree, curnode, 0);
361 }
362
363
TreeBARSub(Tree * aTree,Node * curnode,int which,int index)364 Node* TreeBARSub(Tree* aTree, Node* curnode, int which, int index)
365 {
366 Node* sibling = curnode->parent->child[which];
367
368 if (isRed(sibling))
369 {
370 sibling->red = 0;
371 curnode->parent->red = 1;
372 TreeRotate(aTree, curnode->parent, !which, index);
373 sibling = curnode->parent->child[which];
374 }
375 if (!sibling)
376 curnode = curnode->parent;
377 else if (isBlack(sibling->child[!which]) && isBlack(sibling->child[which]))
378 {
379 sibling->red = 1;
380 curnode = curnode->parent;
381 }
382 else
383 {
384 if (isBlack(sibling->child[which]))
385 {
386 sibling->child[!which]->red = 0;
387 sibling->red = 1;
388 TreeRotate(aTree, sibling, which, index);
389 sibling = curnode->parent->child[which];
390 }
391 sibling->red = curnode->parent->red;
392 curnode->parent->red = 0;
393 sibling->child[which]->red = 0;
394 TreeRotate(aTree, curnode->parent, !which, index);
395 curnode = aTree->index[index].root;
396 }
397 return curnode;
398 }
399
400
TreeBalanceAfterRemove(Tree * aTree,Node * curnode,int index)401 void TreeBalanceAfterRemove(Tree* aTree, Node* curnode, int index)
402 {
403 while (curnode != aTree->index[index].root && isBlack(curnode))
404 {
405 /* curnode->content == NULL must equal curnode == NULL */
406 if (((curnode->content) ? curnode : NULL) == curnode->parent->child[LEFT])
407 curnode = TreeBARSub(aTree, curnode, RIGHT, index);
408 else
409 curnode = TreeBARSub(aTree, curnode, LEFT, index);
410 }
411 curnode->red = 0;
412 }
413
414
415 /**
416 * Remove an item from a tree
417 * @param aTree the list to which the item is to be added
418 * @param curnode the list item content itself
419 */
TreeRemoveNodeIndex(Tree * aTree,Node * curnode,int index)420 void* TreeRemoveNodeIndex(Tree* aTree, Node* curnode, int index)
421 {
422 Node* redundant = curnode;
423 Node* curchild = NULL;
424 size_t size = curnode->size;
425 void* content = curnode->content;
426
427 /* if the node to remove has 0 or 1 children, it can be removed without involving another node */
428 if (curnode->child[LEFT] && curnode->child[RIGHT]) /* 2 children */
429 redundant = TreeSuccessor(curnode); /* now redundant must have at most one child */
430
431 curchild = redundant->child[(redundant->child[LEFT] != NULL) ? LEFT : RIGHT];
432 if (curchild) /* we could have no children at all */
433 curchild->parent = redundant->parent;
434
435 if (redundant->parent == NULL)
436 aTree->index[index].root = curchild;
437 else
438 {
439 if (redundant == redundant->parent->child[LEFT])
440 redundant->parent->child[LEFT] = curchild;
441 else
442 redundant->parent->child[RIGHT] = curchild;
443 }
444
445 if (redundant != curnode)
446 {
447 curnode->content = redundant->content;
448 curnode->size = redundant->size;
449 }
450
451 if (isBlack(redundant))
452 {
453 if (curchild == NULL)
454 {
455 if (redundant->parent)
456 {
457 Node temp;
458 memset(&temp, '\0', sizeof(Node));
459 temp.parent = redundant->parent;
460 temp.red = 0;
461 TreeBalanceAfterRemove(aTree, &temp, index);
462 }
463 }
464 else
465 TreeBalanceAfterRemove(aTree, curchild, index);
466 }
467
468 #if defined(UNIT_TESTS) || defined(NO_HEAP_TRACKING)
469 free(redundant);
470 #else
471 (aTree->heap_tracking) ? myfree(__FILE__, __LINE__, redundant) : free(redundant);
472 #endif
473 if (index == 0)
474 {
475 aTree->size -= size;
476 --(aTree->count);
477 }
478 return content;
479 }
480
481
482 /**
483 * Remove an item from a tree
484 * @param aTree the list to which the item is to be added
485 * @param curnode the list item content itself
486 */
TreeRemoveIndex(Tree * aTree,void * content,int index)487 void* TreeRemoveIndex(Tree* aTree, void* content, int index)
488 {
489 Node* curnode = TreeFindContentIndex(aTree, content, index);
490
491 if (curnode == NULL)
492 return NULL;
493
494 return TreeRemoveNodeIndex(aTree, curnode, index);
495 }
496
497
TreeRemove(Tree * aTree,void * content)498 void* TreeRemove(Tree* aTree, void* content)
499 {
500 int i;
501 void* rc = NULL;
502
503 for (i = 0; i < aTree->indexes; ++i)
504 rc = TreeRemoveIndex(aTree, content, i);
505
506 return rc;
507 }
508
509
TreeRemoveKeyIndex(Tree * aTree,void * key,int index)510 void* TreeRemoveKeyIndex(Tree* aTree, void* key, int index)
511 {
512 Node* curnode = TreeFindIndex(aTree, key, index);
513 void* content = NULL;
514 int i;
515
516 if (curnode == NULL)
517 return NULL;
518
519 content = TreeRemoveNodeIndex(aTree, curnode, index);
520 for (i = 0; i < aTree->indexes; ++i)
521 {
522 if (i != index)
523 content = TreeRemoveIndex(aTree, content, i);
524 }
525 return content;
526 }
527
528
TreeRemoveKey(Tree * aTree,void * key)529 void* TreeRemoveKey(Tree* aTree, void* key)
530 {
531 return TreeRemoveKeyIndex(aTree, key, 0);
532 }
533
534
TreeIntCompare(void * a,void * b,int content)535 int TreeIntCompare(void* a, void* b, int content)
536 {
537 int i = *((int*)a);
538 int j = *((int*)b);
539
540 /* printf("comparing %d %d\n", *((int*)a), *((int*)b)); */
541 return (i > j) ? -1 : (i == j) ? 0 : 1;
542 }
543
544
TreePtrCompare(void * a,void * b,int content)545 int TreePtrCompare(void* a, void* b, int content)
546 {
547 return (a > b) ? -1 : (a == b) ? 0 : 1;
548 }
549
550
TreeStringCompare(void * a,void * b,int content)551 int TreeStringCompare(void* a, void* b, int content)
552 {
553 return strcmp((char*)a, (char*)b);
554 }
555
556
557 #if defined(UNIT_TESTS)
558
check(Tree * t)559 int check(Tree *t)
560 {
561 Node* curnode = NULL;
562 int rc = 0;
563
564 curnode = TreeNextElement(t, curnode);
565 while (curnode)
566 {
567 Node* prevnode = curnode;
568
569 curnode = TreeNextElement(t, curnode);
570
571 if (prevnode && curnode && (*(int*)(curnode->content) < *(int*)(prevnode->content)))
572 {
573 printf("out of order %d < %d\n", *(int*)(curnode->content), *(int*)(prevnode->content));
574 rc = 99;
575 }
576 }
577 return rc;
578 }
579
580
traverse(Tree * t,int lookfor)581 int traverse(Tree *t, int lookfor)
582 {
583 Node* curnode = NULL;
584 int rc = 0;
585
586 printf("Traversing\n");
587 curnode = TreeNextElement(t, curnode);
588 /* printf("content int %d\n", *(int*)(curnode->content)); */
589 while (curnode)
590 {
591 Node* prevnode = curnode;
592
593 curnode = TreeNextElement(t, curnode);
594 /* if (curnode)
595 printf("content int %d\n", *(int*)(curnode->content)); */
596 if (prevnode && curnode && (*(int*)(curnode->content) < *(int*)(prevnode->content)))
597 {
598 printf("out of order %d < %d\n", *(int*)(curnode->content), *(int*)(prevnode->content));
599 }
600 if (curnode && (lookfor == *(int*)(curnode->content)))
601 printf("missing item %d actually found\n", lookfor);
602 }
603 printf("End traverse %d\n", rc);
604 return rc;
605 }
606
607
test(int limit)608 int test(int limit)
609 {
610 int i, *ip, *todelete;
611 Node* current = NULL;
612 Tree* t = TreeInitialize(TreeIntCompare);
613 int rc = 0;
614
615 printf("Tree initialized\n");
616
617 srand(time(NULL));
618
619 ip = malloc(sizeof(int));
620 *ip = 2;
621 TreeAdd(t, (void*)ip, sizeof(int));
622
623 check(t);
624
625 i = 2;
626 void* result = TreeRemove(t, (void*)&i);
627 if (result)
628 free(result);
629
630 int actual[limit];
631 for (i = 0; i < limit; i++)
632 {
633 void* replaced = NULL;
634
635 ip = malloc(sizeof(int));
636 *ip = rand();
637 replaced = TreeAdd(t, (void*)ip, sizeof(int));
638 if (replaced) /* duplicate */
639 {
640 free(replaced);
641 actual[i] = -1;
642 }
643 else
644 actual[i] = *ip;
645 if (i==5)
646 todelete = ip;
647 printf("Tree element added %d\n", *ip);
648 if (1 % 1000 == 0)
649 {
650 rc = check(t);
651 printf("%d elements, check result %d\n", i+1, rc);
652 if (rc != 0)
653 return 88;
654 }
655 }
656
657 check(t);
658
659 for (i = 0; i < limit; i++)
660 {
661 int parm = actual[i];
662
663 if (parm == -1)
664 continue;
665
666 Node* found = TreeFind(t, (void*)&parm);
667 if (found)
668 printf("Tree find %d %d\n", parm, *(int*)(found->content));
669 else
670 {
671 printf("%d not found\n", parm);
672 traverse(t, parm);
673 return -2;
674 }
675 }
676
677 check(t);
678
679 for (i = limit -1; i >= 0; i--)
680 {
681 int parm = actual[i];
682 void *found;
683
684 if (parm == -1) /* skip duplicate */
685 continue;
686
687 found = TreeRemove(t, (void*)&parm);
688 if (found)
689 {
690 printf("%d Tree remove %d %d\n", i, parm, *(int*)(found));
691 free(found);
692 }
693 else
694 {
695 int count = 0;
696 printf("%d %d not found\n", i, parm);
697 traverse(t, parm);
698 for (i = 0; i < limit; i++)
699 if (actual[i] == parm)
700 ++count;
701 printf("%d occurs %d times\n", parm, count);
702 return -2;
703 }
704 if (i % 1000 == 0)
705 {
706 rc = check(t);
707 printf("%d elements, check result %d\n", i+1, rc);
708 if (rc != 0)
709 return 88;
710 }
711 }
712 printf("finished\n");
713 return 0;
714 }
715
main(int argc,char * argv[])716 int main(int argc, char *argv[])
717 {
718 int rc = 0;
719
720 while (rc == 0)
721 rc = test(999999);
722 }
723
724 #endif
725
726
727
728
729
730