Tree.c
Go to the documentation of this file.
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 
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 
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 
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 
78 void TreeAddIndex(Tree* aTree, int(*compare)(void*, void*, int))
79 {
80  aTree->index[aTree->indexes].compare = compare;
81  ++(aTree->indexes);
82 }
83 
84 
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 
103 int isRed(Node* aNode)
104 {
105  return (aNode != NULL) && (aNode->red);
106 }
107 
108 
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 
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 
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 
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 
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 
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 
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 
303 Node* TreeFindIndex(Tree* aTree, void* key, int index)
304 {
305  return TreeFindIndex1(aTree, key, index, 0);
306 }
307 
308 
309 Node* TreeFindContentIndex(Tree* aTree, void* key, int index)
310 {
311  return TreeFindIndex1(aTree, key, index, 1);
312 }
313 
314 
315 Node* TreeFind(Tree* aTree, void* key)
316 {
317  return TreeFindIndex(aTree, key, 0);
318 }
319 
320 
322 {
323  if (curnode)
324  while (curnode->child[LEFT])
325  curnode = curnode->child[LEFT];
326  return curnode;
327 }
328 
329 
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 
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 
358 Node* TreeNextElement(Tree* aTree, Node* curnode)
359 {
360  return TreeNextElementIndex(aTree, curnode, 0);
361 }
362 
363 
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 
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 
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 
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 
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 
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 
529 void* TreeRemoveKey(Tree* aTree, void* key)
530 {
531  return TreeRemoveKeyIndex(aTree, key, 0);
532 }
533 
534 
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 
545 int TreePtrCompare(void* a, void* b, int content)
546 {
547  return (a > b) ? -1 : (a == b) ? 0 : 1;
548 }
549 
550 
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 
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 
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 
608 int test(int limit)
609 {
610  int i, *ip, *todelete;
611  Node* current = NULL;
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 
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 
void * TreeAddByIndex(Tree *aTree, void *content, size_t size, int index)
Definition: Tree.c:210
enum MQTTPropertyCodes value
void TreeAddIndex(Tree *aTree, int(*compare)(void *, void *, int))
Definition: Tree.c:78
void * TreeAdd(Tree *aTree, void *content, size_t size)
Definition: Tree.c:274
int TreePtrCompare(void *a, void *b, int content)
Definition: Tree.c:545
Node * TreeSuccessor(Node *curnode)
Definition: Tree.c:330
lu_byte right
Definition: lparser.c:1229
unsigned int allow_duplicates
Definition: Tree.h:87
lu_byte left
Definition: lparser.c:1228
void * TreeRemoveKey(Tree *aTree, void *key)
Definition: Tree.c:529
Node * TreeNextElementIndex(Tree *aTree, Node *curnode, int index)
Definition: Tree.c:348
size_t size
Definition: Tree.h:85
#define malloc(x)
Definition: Heap.h:41
#define RIGHT
Definition: Tree.c:96
int indexes
Definition: Tree.h:83
void * mymalloc(char *file, int line, size_t size)
Definition: Heap.c:158
Node * TreeMinimum(Node *curnode)
Definition: Tree.c:321
void * TreeRemoveKeyIndex(Tree *aTree, void *key, int index)
Definition: Tree.c:510
Node * TreeBAASub(Tree *aTree, Node *curnode, int which, int index)
Definition: Tree.c:166
int isRed(Node *aNode)
Definition: Tree.c:103
#define free(x)
Definition: Heap.h:55
void * TreeRemove(Tree *aTree, void *content)
Definition: Tree.c:498
int TreeIntCompare(void *a, void *b, int content)
Definition: Tree.c:535
void * TreeRemoveNodeIndex(Tree *aTree, Node *curnode, int index)
Definition: Tree.c:420
constexpr size_t count()
Definition: core.h:960
void myfree(char *file, int line, void *p)
Definition: Heap.c:277
unsigned int heap_tracking
Definition: Tree.h:86
int count
Definition: Tree.h:83
void TreeInitializeNoMalloc(Tree *aTree, int(*compare)(void *, void *, int))
Definition: Tree.c:53
Node * TreeNextElement(Tree *aTree, Node *curnode)
Definition: Tree.c:358
struct Tree::@72 index[2]
Tree * TreeInitialize(int(*compare)(void *, void *, int))
Definition: Tree.c:65
Definition: Tree.h:76
Node * TreeFind(Tree *aTree, void *key)
Definition: Tree.c:315
static void check(LexState *ls, int c)
Definition: lparser.c:107
void TreeBalanceAfterRemove(Tree *aTree, Node *curnode, int index)
Definition: Tree.c:401
void TreeRotate(Tree *aTree, Node *curnode, int direction, int index)
Definition: Tree.c:147
Node * TreeFindIndex1(Tree *aTree, void *key, int index, int value)
Definition: Tree.c:286
Node * root
Definition: Tree.h:80
#define max(a, b)
Definition: Tree.c:98
float time
Definition: mqtt_test.py:17
void * TreeRemoveIndex(Tree *aTree, void *content, int index)
Definition: Tree.c:487
Node * TreeFindIndex(Tree *aTree, void *key, int index)
Definition: Tree.c:303
#define LEFT
Definition: Tree.c:95
Node * TreeBARSub(Tree *aTree, Node *curnode, int which, int index)
Definition: Tree.c:364
void TreeFree(Tree *aTree)
Definition: Tree.c:85
int isBlack(Node *aNode)
Definition: Tree.c:109
Node * TreeFindContentIndex(Tree *aTree, void *key, int index)
Definition: Tree.c:309
Definition: lobject.h:674
void TreeBalanceAfterAdd(Tree *aTree, Node *curnode, int index)
Definition: Tree.c:191
int(* compare)(void *, void *, int)
Definition: Tree.h:81
enum MQTTReasonCodes rc
Definition: test10.c:1112
int main(int argc, char **argv)
Definition: lua.c:619
int TreeStringCompare(void *a, void *b, int content)
Definition: Tree.c:551


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Dec 6 2020 04:02:48