• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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