Rudiments
avltreeinlines.h
1 // Copyright (c) 1999-2018 David Muse
2 // See the COPYING file for more information
3 
4 //#define DEBUG_AVLTREE 1
5 
6 #include <rudiments/stdio.h>
7 #include <rudiments/private/nodeinlines.h>
8 
9 #define AVLTREE_TEMPLATE template <class valuetype>
10 
11 #define AVLTREE_CLASS avltree<valuetype>
12 
13 #define AVLTREENODE_TEMPLATE template <class valuetype>
14 
15 #define AVLTREENODE_CLASS avltreenode<valuetype>
16 
17 AVLTREE_TEMPLATE
18 inline
19 AVLTREE_CLASS::avltree() {
20  top=NULL;
21  first=NULL;
22  last=NULL;
23  length=0;
24 }
25 
26 AVLTREE_TEMPLATE
27 inline
28 AVLTREE_CLASS::~avltree() {
29  clear();
30 }
31 
32 AVLTREE_TEMPLATE
33 inline
34 void AVLTREE_CLASS::insert(valuetype value) {
35  insert(new avltreenode<valuetype>(value));
36 }
37 
38 AVLTREE_TEMPLATE
39 inline
40 void AVLTREE_CLASS::insert(avltreenode<valuetype> *node) {
41 
42  // degenerate case
43  if (!node) {
44  return;
45  }
46 
47  #ifdef DEBUG_AVLTREE
48  stdoutput.printf("----------------------------------------"
49  "---------------------------------------\n");
50  #endif
51 
52  if (top) {
53 
54  // insert the node, optionally replacing the top of the tree
55  top->insert(node,&top);
56 
57  // update first
58  for (first=top;
59  first->getLeftChild();
60  first=first->getLeftChild()) {}
61 
62  // update last
63  for (last=top;
64  last->getRightChild();
65  last=last->getRightChild()) {}
66  } else {
67 
68  // if there was no top node, then this is the
69  // first node inserted into the entire tree
70  top=node;
71  first=node;
72  last=node;
73  }
74 
75  // increment length
76  length++;
77 }
78 
79 AVLTREE_TEMPLATE
80 inline
81 avltreenode<valuetype> *AVLTREE_CLASS::detach(avltreenode<valuetype> *node) {
82 
83  // degenerate case
84  if (!node) {
85  return NULL;
86  }
87 
88  #ifdef DEBUG_AVLTREE
89  stdoutput.printf("----------------------------------------"
90  "---------------------------------------\n");
91  #endif
92 
93  // update first
94  if (first==node) {
95  first=node->getNext();
96  }
97 
98  // update last
99  if (last==node) {
100  last=node->getPrevious();
101  }
102 
103  // detach the node
104  node->detach(&top);
105 
106  // decrement length
107  length--;
108 
109  return node;
110 }
111 
112 AVLTREE_TEMPLATE
113 inline
114 bool AVLTREE_CLASS::remove(valuetype value) {
115  avltreenode<valuetype> *current=find(value);
116  return (current)?remove(current):false;
117 }
118 
119 AVLTREE_TEMPLATE
120 inline
121 bool AVLTREE_CLASS::removeAndDelete(valuetype value) {
122  avltreenode<valuetype> *current=find(value);
123  return (current)?removeAndDelete(current):false;
124 }
125 
126 AVLTREE_TEMPLATE
127 inline
128 bool AVLTREE_CLASS::removeAndArrayDelete(valuetype value) {
129  avltreenode<valuetype> *current=find(value);
130  return (current)?removeAndArrayDelete(current):false;
131 }
132 
133 AVLTREE_TEMPLATE
134 inline
135 bool AVLTREE_CLASS::removeAll(valuetype value) {
136  bool removed=false;
137  while (remove(value)) {
138  removed=true;
139  }
140  return removed;
141 }
142 
143 AVLTREE_TEMPLATE
144 inline
145 bool AVLTREE_CLASS::removeAllAndDelete(valuetype value) {
146  bool removed=false;
147  while (removeAndDelete(value)) {
148  removed=true;
149  }
150  return removed;
151 }
152 
153 AVLTREE_TEMPLATE
154 inline
155 bool AVLTREE_CLASS::removeAllAndArrayDelete(valuetype value) {
156  bool removed=false;
157  while (removeAndArrayDelete(value)) {
158  removed=true;
159  }
160  return removed;
161 }
162 
163 AVLTREE_TEMPLATE
164 inline
165 bool AVLTREE_CLASS::remove(avltreenode<valuetype> *node) {
166  delete detach(node);
167  return true;
168 }
169 
170 AVLTREE_TEMPLATE
171 inline
172 bool AVLTREE_CLASS::removeAndDelete(avltreenode<valuetype> *node) {
173  avltreenode<valuetype> *detachednode=detach(node);
174  delete detachednode->getValue();
175  delete detachednode;
176  return true;
177 }
178 
179 AVLTREE_TEMPLATE
180 inline
181 bool AVLTREE_CLASS::removeAndArrayDelete(avltreenode<valuetype> *node) {
182  avltreenode<valuetype> *detachednode=detach(node);
183  delete[] detachednode->getValue();
184  delete detachednode;
185  return true;
186 }
187 
188 AVLTREE_TEMPLATE
189 inline
190 uint64_t AVLTREE_CLASS::getLength() const {
191  return length;
192 }
193 
194 AVLTREE_TEMPLATE
195 inline
196 avltreenode<valuetype> *AVLTREE_CLASS::getTop() {
197  return top;
198 }
199 
200 AVLTREE_TEMPLATE
201 inline
202 avltreenode<valuetype> *AVLTREE_CLASS::getFirst() {
203  return first;
204 }
205 
206 AVLTREE_TEMPLATE
207 inline
208 avltreenode<valuetype> *AVLTREE_CLASS::getLast() {
209  return last;
210 }
211 
212 AVLTREE_TEMPLATE
213 inline
214 avltreenode<valuetype> *AVLTREE_CLASS::getPrevious(
215  avltreenode<valuetype> *node) {
216  return (node)?node->getPrevious():NULL;
217 }
218 
219 AVLTREE_TEMPLATE
220 inline
221 avltreenode<valuetype> *AVLTREE_CLASS::getNext(
222  avltreenode<valuetype> *node) {
223  return (node)?node->getNext():NULL;
224 }
225 
226 AVLTREE_TEMPLATE
227 inline
228 avltreenode<valuetype> *AVLTREE_CLASS::find(valuetype value) {
229  return find((avltreenode<valuetype> *)top,value);
230 }
231 
232 AVLTREE_TEMPLATE
233 inline
234 avltreenode<valuetype> *AVLTREE_CLASS::find(
235  avltreenode<valuetype> *startnode,
236  valuetype value) {
237 
238  #ifdef DEBUG_AVLTREE
239  stdoutput.printf("find ");
240  node_print(value);
241  stdoutput.printf(" from ");
242  if (startnode) {
243  node_print(startnode->getValue());
244  } else {
245  node_print("(null)");
246  }
247  stdoutput.printf(" {\n");
248  #endif
249 
250  // descend the tree until we find the value or run off of the bottom
251  avltreenode<valuetype> *current=startnode;
252  while (current) {
253 
254  int32_t result=current->compare(value);
255 
256  #ifdef DEBUG_AVLTREE
257  stdoutput.printf(" ");
258  node_print(current->getValue());
259  stdoutput.printf(" - %d\n",result);
260  #endif
261 
262  if (result<0) {
263  current=current->getRightChild();
264  } else if (result==0) {
265  break;
266  } else if (result>0) {
267  current=current->getLeftChild();
268  }
269  }
270 
271  #ifdef DEBUG_AVLTREE
272  if (current) {
273  stdoutput.printf(" success!\n");
274  } else {
275  stdoutput.printf(" failed\n");
276  }
277  stdoutput.printf("} find\n\n");
278  #endif
279 
280  return current;
281 }
282 
283 // NOTE: Don't collapse the clear methods into a single method, or the compiler
284 // will attempt to compile calls to:
285 // delete current->getValue();
286 // and
287 // delete[] current->getValue();
288 // even if the app just calls clear(). This will fail for primitive types or
289 // when the type has a private destructor.
290 
291 AVLTREE_TEMPLATE
292 inline
293 void AVLTREE_CLASS::clear() {
294 
295  #ifdef DEBUG_AVLTREE
296  uint64_t i=0;
297  stdoutput.printf("clearing %d nodes {\n",length);
298  #endif
299 
300  // start at the top
301  AVLTREENODE_CLASS *node=top;
302  while (node) {
303 
304  // go right one, then go left as far as possible
305  if (node->getRightChild()) {
306  node=node->getRightChild();
307  }
308  while (node->getLeftChild()) {
309  node=node->getLeftChild();
310  }
311 
312  // get the parent
313  AVLTREENODE_CLASS *p=node->getParent();
314  if (p) {
315  if (p->getLeftChild()==node) {
316  p->setLeftChild(NULL);
317  } else {
318  p->setRightChild(NULL);
319  }
320  }
321 
322  // delete the node
323  #ifdef DEBUG_AVLTREE
324  stdoutput.printf(" clearing %lld\n",i);
325  // It's dangerous to try to print the value of the node here.
326  // If the value is a pointer to something, it may have been
327  // deleted already. In fact, it's really common to run through
328  // the tree, deleting values, before finally calling clear()
329  // on the tree itself.
330  i++;
331  #endif
332  delete node;
333 
334  // continue with parent...
335  node=p;
336  }
337 
338  #ifdef DEBUG_AVLTREE
339  stdoutput.printf("} cleared %d nodes\n\n",i);
340  #endif
341 
342  // clear pointers and length
343  top=NULL;
344  first=NULL;
345  last=NULL;
346  length=0;
347 }
348 
349 AVLTREE_TEMPLATE
350 inline
351 void AVLTREE_CLASS::clearAndDelete() {
352 
353  #ifdef DEBUG_AVLTREE
354  uint64_t i=0;
355  stdoutput.printf("clearing %d nodes {\n",length);
356  #endif
357 
358  // start at the top
359  AVLTREENODE_CLASS *node=top;
360  while (node) {
361 
362  // go right one, then go left as far as possible
363  if (node->getRightChild()) {
364  node=node->getRightChild();
365  }
366  while (node->getLeftChild()) {
367  node=node->getLeftChild();
368  }
369 
370  // get the parent
371  AVLTREENODE_CLASS *p=node->getParent();
372  if (p) {
373  if (p->getLeftChild()==node) {
374  p->setLeftChild(NULL);
375  } else {
376  p->setRightChild(NULL);
377  }
378  }
379 
380  // delete the node
381  #ifdef DEBUG_AVLTREE
382  stdoutput.printf(" clearing %lld\n",i);
383  i++;
384  #endif
385  delete node->getValue();
386  delete node;
387 
388  // continue with parent...
389  node=p;
390  }
391 
392  #ifdef DEBUG_AVLTREE
393  stdoutput.printf("} cleared %d nodes\n\n",i);
394  #endif
395 
396  // clear pointers and length
397  top=NULL;
398  first=NULL;
399  last=NULL;
400  length=0;
401 }
402 
403 AVLTREE_TEMPLATE
404 inline
405 void AVLTREE_CLASS::clearAndArrayDelete() {
406 
407  #ifdef DEBUG_AVLTREE
408  uint64_t i=0;
409  stdoutput.printf("clearing %d nodes {\n",length);
410  #endif
411 
412  // start at the top
413  AVLTREENODE_CLASS *node=top;
414  while (node) {
415 
416  // go right one, then go left as far as possible
417  if (node->getRightChild()) {
418  node=node->getRightChild();
419  }
420  while (node->getLeftChild()) {
421  node=node->getLeftChild();
422  }
423 
424  // get the parent
425  AVLTREENODE_CLASS *p=node->getParent();
426  if (p) {
427  if (p->getLeftChild()==node) {
428  p->setLeftChild(NULL);
429  } else {
430  p->setRightChild(NULL);
431  }
432  }
433 
434  // delete the node
435  #ifdef DEBUG_AVLTREE
436  stdoutput.printf(" clearing %lld\n",i);
437  i++;
438  #endif
439  delete[] node->getValue();
440  delete node;
441 
442  // continue with parent...
443  node=p;
444  }
445 
446  #ifdef DEBUG_AVLTREE
447  stdoutput.printf("} cleared %d nodes\n\n",i);
448  #endif
449 
450  // clear pointers and length
451  top=NULL;
452  first=NULL;
453  last=NULL;
454  length=0;
455 }
456 
457 AVLTREE_TEMPLATE
458 inline
459 void AVLTREE_CLASS::print() const {
460  if (top) {
461  top->print();
462  }
463 }
464 
465 AVLTREENODE_TEMPLATE
466 inline
467 AVLTREENODE_CLASS::avltreenode(valuetype value) {
468  this->value=value;
469  parent=NULL;
470  left=NULL;
471  right=NULL;
472  leftheight=0;
473  rightheight=0;
474 }
475 
476 AVLTREENODE_TEMPLATE
477 inline
478 AVLTREENODE_CLASS::~avltreenode() {
479 }
480 
481 AVLTREENODE_TEMPLATE
482 inline
483 void AVLTREENODE_CLASS::setValue(valuetype value) {
484  this->value=value;
485 }
486 
487 AVLTREENODE_TEMPLATE
488 inline
489 valuetype AVLTREENODE_CLASS::getValue() const {
490  return value;
491 }
492 
493 AVLTREENODE_TEMPLATE
494 inline
495 AVLTREENODE_CLASS *AVLTREENODE_CLASS::getParent() {
496  return parent;
497 }
498 
499 AVLTREENODE_TEMPLATE
500 inline
501 AVLTREENODE_CLASS *AVLTREENODE_CLASS::getLeftChild() {
502  return left;
503 }
504 
505 AVLTREENODE_TEMPLATE
506 inline
507 AVLTREENODE_CLASS *AVLTREENODE_CLASS::getRightChild() {
508  return right;
509 }
510 
511 AVLTREENODE_TEMPLATE
512 inline
513 uint8_t AVLTREENODE_CLASS::getLeftHeight() {
514  return leftheight;
515 }
516 
517 AVLTREENODE_TEMPLATE
518 inline
519 uint8_t AVLTREENODE_CLASS::getRightHeight() {
520  return rightheight;
521 }
522 
523 AVLTREENODE_TEMPLATE
524 inline
525 AVLTREENODE_CLASS *AVLTREENODE_CLASS::getPrevious() {
526 
527  // reverse in-order, depth-first traversal...
528 
529  if (left) {
530 
531  // if we have a left child then its rightmost descendent
532  // contains the next lowest value...
533 
534  // go left
535  AVLTREENODE_CLASS *node=left;
536 
537  // go as far right as possible
538  while (node->right) {
539  node=node->right;
540  }
541  return node;
542 
543  } else if (parent) {
544 
545  // if we're the right child of our parent,
546  // then our parent contains the next lowest value
547  if (parent->right==this) {
548  return parent;
549  }
550 
551  // If we're the left child of our parent, then we have to
552  // move up until we find an acestor that's the right child of
553  // its parent. That node contains the next lowest value.
554  AVLTREENODE_CLASS *node=parent;
555  while (node) {
556  if (!node->parent) {
557  break;
558  }
559  if (node->parent->right==node) {
560  return node->parent;
561  }
562  node=node->parent;
563  }
564  }
565  return NULL;
566 }
567 
568 AVLTREENODE_TEMPLATE
569 inline
570 AVLTREENODE_CLASS *AVLTREENODE_CLASS::getNext() {
571 
572  // in-order, depth-first traversal...
573 
574  if (right) {
575 
576  // if we have a right child then its leftmost descendent
577  // contains the next highest value...
578 
579  // go right
580  AVLTREENODE_CLASS *node=right;
581 
582  // go as far left as possible
583  while (node->left) {
584  node=node->left;
585  }
586  return node;
587 
588  } else if (parent) {
589 
590  // if we're the left child of our parent,
591  // then our parent contains the next highest value
592  if (parent->left==this) {
593  return parent;
594  }
595 
596  // If we're the right child of our parent, then we have to
597  // move up until we find an acestor that's the left child of
598  // its parent. That node contains the next highest value.
599  AVLTREENODE_CLASS *node=parent;
600  while (node) {
601  if (!node->parent) {
602  break;
603  }
604  if (node->parent->left==node) {
605  return node->parent;
606  }
607  node=node->parent;
608  }
609  }
610  return NULL;
611 }
612 
613 AVLTREENODE_TEMPLATE
614 inline
615 int32_t AVLTREENODE_CLASS::compare(valuetype value) const {
616  return node_compare(this->value,value);
617 }
618 
619 AVLTREENODE_TEMPLATE
620 inline
621 int32_t AVLTREENODE_CLASS::compare(avltreenode<valuetype> *peer) const {
622  return node_compare(this->value,peer->value);
623 }
624 
625 AVLTREENODE_TEMPLATE
626 inline
627 void AVLTREENODE_CLASS::print() const {
628  uint16_t indentlevel=0;
629  print("top",&indentlevel);
630 }
631 
632 AVLTREENODE_TEMPLATE
633 inline
634 void AVLTREENODE_CLASS::print(const char *name, uint16_t *indentlevel) const {
635  // print an xml-style representation of the node and its descendents
636  for (uint16_t i=0; i<*indentlevel; i++) {
637  stdoutput.printf(" ");
638  }
639  stdoutput.printf("<%s value=\"",name);
640  node_print(value);
641  stdoutput.printf("\" lh=\"%d\" rh=\"%d\" bf=\"%d\"",
642  leftheight,rightheight,leftheight-rightheight);
643  if (!left && !right) {
644  stdoutput.printf("/>\n");
645  } else {
646  stdoutput.printf(">\n");
647  (*indentlevel)++;
648  if (left) {
649  left->print("left ",indentlevel);
650  }
651  if (right) {
652  right->print("right",indentlevel);
653  }
654  (*indentlevel)--;
655  for (uint16_t i=0; i<*indentlevel; i++) {
656  stdoutput.printf(" ");
657  }
658  stdoutput.printf("</%s>\n",name);
659  }
660 }
661 
662 AVLTREENODE_TEMPLATE
663 inline
664 void AVLTREENODE_CLASS::setParent(AVLTREENODE_CLASS *node) {
665  parent=node;
666 }
667 
668 AVLTREENODE_TEMPLATE
669 inline
670 void AVLTREENODE_CLASS::setLeftChild(AVLTREENODE_CLASS *node) {
671  left=node;
672 }
673 
674 AVLTREENODE_TEMPLATE
675 inline
676 void AVLTREENODE_CLASS::setRightChild(AVLTREENODE_CLASS *node) {
677  right=node;
678 }
679 
680 AVLTREE_TEMPLATE
681 inline
682 void AVLTREENODE_CLASS::insert(avltreenode<valuetype> *node,
683  avltreenode<valuetype> **treetop) {
684 
685  // degenerate case
686  if (!node) {
687  return;
688  }
689 
690  // find a location to insert the node (should always be a leaf node)
691  avltreenode<valuetype> *location=this;
692  for (;;) {
693 
694  if (node->compare(location->value)<=0) {
695 
696  if (location->left) {
697  location=location->left;
698  } else {
699 
700  #ifdef DEBUG_AVLTREE
701  stdoutput.printf("insert ");
702  node_print(node->value);
703  stdoutput.printf(" to left of ");
704  node_print(location->value);
705  stdoutput.printf(" {\n\n");
706  #endif
707 
708  location->setLeftChild(node);
709  break;
710  }
711 
712  } else if (node->compare(location->value)>0) {
713 
714  if (location->right) {
715  location=location->right;
716  } else {
717 
718  #ifdef DEBUG_AVLTREE
719  stdoutput.printf("insert ");
720  node_print(node->value);
721  stdoutput.printf(" to right of ");
722  node_print(location->value);
723  stdoutput.printf(" {\n\n");
724  #endif
725 
726  location->setRightChild(node);
727  break;
728  }
729  }
730  }
731 
732  node->setParent(location);
733 
734  // update heights up the tree
735  adjustParentHeights(node);
736 
737  // balance the tree
738  node->parent->balance(treetop);
739 
740  #ifdef DEBUG_AVLTREE
741  stdoutput.printf("} insert\n\n");
742  #endif
743 }
744 
745 AVLTREE_TEMPLATE
746 inline
747 void AVLTREENODE_CLASS::detach(avltreenode<valuetype> **treetop) {
748 
749  #ifdef DEBUG_AVLTREE
750  stdoutput.printf("detach ");
751  node_print(value);
752  stdoutput.printf(" {\n\n");
753 
754  avltreenode<valuetype> *top=this;
755  while (top->parent) { top=top->parent; }
756  top->print(); stdoutput.printf("\n");
757  #endif
758 
759  if (left && right) {
760 
761  // node with left and right children...
762 
763  #ifdef DEBUG_AVLTREE
764  stdoutput.printf("less simple case: 2 children\n\n");
765  #endif
766 
767  // get this node's successor...
768  //
769  // (eg. if the tree contains values 5, 7, 10, 12, 15, and 18,
770  // and this node is 10, then find the node with 12 in it)
771  //
772  // following the rules from our in-order, depth-first traversal
773  // above, since we have a right child, we must go right one,
774  // then go left as far as possible
775  avltreenode<valuetype> *successor=right;
776  while (successor->left) {
777  successor=successor->left;
778  }
779 
780  #ifdef DEBUG_AVLTREE
781  stdoutput.printf("swap ");
782  node_print(value);
783  stdoutput.printf(" and ");
784  node_print(successor->value);
785  stdoutput.printf("\n\n");
786  #endif
787 
788 
789  // if the successor was the immediate right child of this node
790  // then we need to handle a few things differently later
791  bool successorwasimmediaterightchild=(right==successor);
792 
793 
794  // swap this node with the successor...
795 
796  // get a copy of the successor
797  avltreenode<valuetype> temp(*successor);
798 
799  // re-parent the successor
800  successor->parent=parent;
801  if (successor->parent) {
802  if (successor->parent->left==this) {
803  successor->parent->left=successor;
804  } else {
805  successor->parent->right=successor;
806  }
807  } else {
808  *treetop=successor;
809  }
810 
811  // replace the successor's children
812  // with those of this node
813  successor->left=left;
814  if (successor->left) {
815  successor->left->parent=successor;
816  }
817  if (successorwasimmediaterightchild) {
818  successor->right=this;
819  successor->right->parent=successor;
820  } else {
821  successor->right=right;
822  if (successor->right) {
823  successor->right->parent=successor;
824  }
825 
826  // re-parent this node
827  parent=temp.parent;
828  if (parent->left==successor) {
829  parent->left=this;
830  } else {
831  parent->right=this;
832  }
833  }
834 
835  // replace the successor's heights
836  // with those of this node
837  successor->leftheight=leftheight;
838  successor->rightheight=rightheight;
839 
840 
841  // replace this node's children
842  // with those of the successor
843  left=temp.left;
844  if (left) {
845  left->parent=this;
846  }
847  right=temp.right;
848  if (right) {
849  right->parent=this;
850  }
851 
852  // replace this node's heights
853  // with those of the successor
854  leftheight=temp.leftheight;
855  rightheight=temp.rightheight;
856 
857  #ifdef DEBUG_AVLTREE
858  avltreenode<valuetype> *top=this;
859  while (top->parent) { top=top->parent; }
860  top->print(); stdoutput.printf("\n");
861  #endif
862 
863  // fall through to the code below because now
864  // the node should have one or zero children...
865  }
866 
867  // node with one or zero children...
868 
869  #ifdef DEBUG_AVLTREE
870  stdoutput.printf("simple case: 1 or 0 children\n\n");
871  #endif
872 
873  // decide which child the node has
874  // NOTE: If the node has no children then this will implicitly
875  // set child=NULL (which is what we want in that case) because
876  // right=NULL.
877  avltreenode<valuetype> *child=(left)?left:right;
878 
879  if (parent) {
880 
881  // disconnect this node from its children
882  left=NULL;
883  right=NULL;
884 
885  // connect the parent to the child
886  // (or to NULL if the node has no children)
887  // decrement the appropriate height of parent
888  if (parent->left==this) {
889  parent->left=child;
890  parent->leftheight--;
891  } else {
892  parent->right=child;
893  parent->rightheight--;
894  }
895 
896  // connect the child to the parent
897  if (child) {
898  child->parent=parent;
899  }
900 
901  // disconnect this node from its parent
902  // (but keep track of the parent so we
903  // can use it to balance)
904  avltreenode<valuetype> *p=parent;
905  parent=NULL;
906 
907  // update heights up the tree
908  adjustParentHeights(p);
909 
910  // balance the tree
911  p->balance(treetop);
912 
913  } else {
914 
915  // disconnect this node's child from it
916  if (child) {
917  child->parent=NULL;
918  }
919 
920  // disconnect this node from its children
921  left=NULL;
922  right=NULL;
923 
924  // NOTE: If the node has no children, then this will
925  // implicitly (re)set treetop=NULL, which is what
926  // we want in that case.
927  *treetop=child;
928 
929  #ifdef DEBUG_AVLTREE
930  avltreenode<valuetype> *top=this;
931  while (top->parent) { top=top->parent; }
932  top->print(); stdoutput.printf("\n");
933  #endif
934  }
935 
936  #ifdef DEBUG_AVLTREE
937  stdoutput.printf("} detach\n\n");
938  #endif
939 }
940 
941 AVLTREE_TEMPLATE
942 inline
943 void AVLTREENODE_CLASS::adjustParentHeights(avltreenode<valuetype> *node) {
944 
945  // move up the tree, starting with the parent of "node"...
946  while (node->parent) {
947 
948  // calculate the new height of the parent
949  uint8_t height=((node->leftheight>node->rightheight)?
950  node->leftheight:
951  node->rightheight)+1;
952 
953  // If "node" is the left child of the parent, then adjust the
954  // parent's left height.
955  // If "node" is the right child of the parent, then adjust the
956  // parent's right height.
957  // In either case, bail if the height is already the same as we
958  // calculated.
959  if (node->parent->left==node) {
960  if (node->parent->leftheight==height) {
961  return;
962  }
963  node->parent->leftheight=height;
964  } else {
965  if (node->parent->rightheight==height) {
966  return;
967  }
968  node->parent->rightheight=height;
969  }
970 
971  // move up
972  node=node->parent;
973  }
974 }
975 
976 AVLTREE_TEMPLATE
977 inline
978 void AVLTREENODE_CLASS::balance(avltreenode<valuetype> **treetop) {
979 
980  // AVL balance...
981 
982  #ifdef DEBUG_AVLTREE
983  stdoutput.printf("balance at ");
984  node_print(value);
985  stdoutput.printf(" {\n\n");
986 
987  avltreenode<valuetype> *top=this;
988  while (top->parent) { top=top->parent; }
989  top->print(); stdoutput.printf("\n");
990  #endif
991 
992  // start balancing with the current node
993  avltreenode<valuetype> *node=this;
994  while (node) {
995 
996  // there's an imbalance if the left and right
997  // tree heights differ by more than 1
998  if ((node->leftheight>node->rightheight &&
999  node->leftheight-node->rightheight>1) ||
1000  (node->rightheight>node->leftheight &&
1001  node->rightheight-node->leftheight>1)) {
1002 
1003  #ifdef DEBUG_AVLTREE
1004  stdoutput.printf("imbalance at ");
1005  node_print(node->value);
1006  stdoutput.printf("\n\n");
1007  #endif
1008 
1009  // apply the appropriate rotation to restore balance
1010  // and let the rotation method tell us whch node to
1011  // process next
1012  if (node->rightheight>node->leftheight) {
1013  if (node->right->rightheight>
1014  node->right->leftheight) {
1015  node=node->leftRotate(treetop);
1016  } else {
1017  node=node->rightLeftRotate(treetop);
1018  }
1019  } else if (node->leftheight>node->rightheight) {
1020  if (node->left->leftheight>
1021  node->left->rightheight) {
1022  node=node->rightRotate(treetop);
1023  } else {
1024  node=node->leftRightRotate(treetop);
1025  }
1026  }
1027 
1028  #ifdef DEBUG_AVLTREE
1029  avltreenode<valuetype> *top=this;
1030  while (top->parent) { top=top->parent; }
1031  top->print(); stdoutput.printf("\n");
1032  #endif
1033 
1034  } else {
1035 
1036  #ifdef DEBUG_AVLTREE
1037  stdoutput.printf("no imbalance at ");
1038  node_print(node->value);
1039  stdoutput.printf("\n\n");
1040  #endif
1041 
1042  // if there's no imbalance then the next node we need
1043  // to process is the parent of the current node
1044  node=node->parent;
1045  }
1046 
1047  #ifdef DEBUG_AVLTREE
1048  if (node) {
1049  stdoutput.printf("continuing at ");
1050  node_print(node->value);
1051  stdoutput.printf("\n\n");
1052  }
1053  #endif
1054  }
1055 
1056 
1057  #ifdef DEBUG_AVLTREE
1058  stdoutput.printf("} balance\n\n");
1059  #endif
1060 }
1061 
1062 AVLTREE_TEMPLATE
1063 inline
1064 avltreenode<valuetype> *AVLTREENODE_CLASS::leftRotate(
1065  avltreenode<valuetype> **treetop) {
1066 
1067  /* one of these: (eg: insert order a,b,c)
1068  *
1069  * \
1070  * a
1071  * / \ \
1072  * b -> b
1073  * / \ / \
1074  * * c a c
1075  * / \ / \ / \
1076  * *
1077  * needs left rotation */
1078 
1079  #ifdef DEBUG_AVLTREE
1080  stdoutput.printf("left rotation at ");
1081  node_print(value);
1082  stdoutput.printf("\n\n");
1083  #endif
1084 
1085  // get a, b, and "star"
1086  avltreenode<valuetype> *a=this;
1087  avltreenode<valuetype> *b=a->right;
1088  avltreenode<valuetype> *star=b->left;
1089  uint8_t starheight=b->leftheight;
1090 
1091  // move b
1092  avltreenode<valuetype> *p=a->parent;
1093  if (p) {
1094  if (p->right==a) {
1095  p->right=b;
1096  } else {
1097  p->left=b;
1098  }
1099  } else {
1100  #ifdef DEBUG_AVLTREE
1101  stdoutput.printf("(new tree top)\n\n");
1102  #endif
1103  *treetop=b;
1104  }
1105  b->parent=a->parent;
1106  b->left=a;
1107 
1108  // move a
1109  a->parent=b;
1110  a->right=star;
1111  a->rightheight=starheight;
1112 
1113  // move "star"
1114  if (star) {
1115  star->parent=a;
1116  }
1117 
1118  // update heights up the tree
1119  adjustParentHeights(a);
1120 
1121  // Since a was moved into a location in the tree that may not have
1122  // prevoiusly existed, and thus may have unbalanced the tree, we need
1123  // to continue balancing, starting at a.
1124  return a;
1125 }
1126 
1127 AVLTREE_TEMPLATE
1128 inline
1129 avltreenode<valuetype> *AVLTREENODE_CLASS::rightLeftRotate(
1130  avltreenode<valuetype> **treetop) {
1131 
1132  /* one of these: (eg: insert order a,c,b)
1133  *
1134  * \ \
1135  * a a
1136  * / \ / \ \
1137  * c -> b -> b
1138  * / \ / \ / \
1139  * b c a c
1140  * / \ / \ / \ / \
1141  * * *
1142  *
1143  * needs right-left rotation */
1144 
1145  #ifdef DEBUG_AVLTREE
1146  stdoutput.printf("right-left rotation at ");
1147  node_print(value);
1148  stdoutput.printf(" {\n\n");
1149  stdoutput.printf("right part\n\n");
1150  #endif
1151 
1152  // do the right part of the right-left rotation...
1153 
1154  // get a, c, b, and "star"
1155  avltreenode<valuetype> *a=this;
1156  avltreenode<valuetype> *c=a->right;
1157  avltreenode<valuetype> *b=c->left;
1158  avltreenode<valuetype> *star=b->right;
1159  uint8_t starheight=b->rightheight;
1160 
1161  // move b
1162  a->right=b;
1163  b->parent=a;
1164  b->right=c;
1165 
1166  // move c
1167  c->parent=b;
1168  c->left=star;
1169  c->leftheight=starheight;
1170 
1171  // move "star"
1172  if (star) {
1173  star->parent=c;
1174  }
1175 
1176  // update heights up the tree
1177  adjustParentHeights(c);
1178 
1179  #ifdef DEBUG_AVLTREE
1180  avltreenode<valuetype> *top=this;
1181  while (top->parent) { top=top->parent; }
1182  top->print(); stdoutput.printf("\n");
1183  #endif
1184 
1185  // do the left part of the right-left rotation
1186  leftRotate(treetop);
1187 
1188  #ifdef DEBUG_AVLTREE
1189  stdoutput.printf("} right-left\n\n");
1190  #endif
1191 
1192  // Since c was moved into a location in the tree that may not have
1193  // prevoiusly existed, and thus may have unbalanced the tree, we need
1194  // to continue balancing, starting at c.
1195  return c;
1196 }
1197 
1198 AVLTREE_TEMPLATE
1199 inline
1200 avltreenode<valuetype> *AVLTREENODE_CLASS::rightRotate(
1201  avltreenode<valuetype> **treetop) {
1202 
1203  /* one of these: (insert order c,b,a)
1204  *
1205  * \
1206  * c
1207  * / \ \
1208  * b -> b
1209  * / \ / \
1210  * a * a c
1211  * / \ / \ / \
1212  * *
1213  * needs right rotation */
1214 
1215  #ifdef DEBUG_AVLTREE
1216  stdoutput.printf("right rotation at ");
1217  node_print(value);
1218  stdoutput.printf("\n\n");
1219  #endif
1220 
1221  // get c, b, and "star"
1222  avltreenode<valuetype> *c=this;
1223  avltreenode<valuetype> *b=c->left;
1224  avltreenode<valuetype> *star=b->right;
1225  uint8_t starheight=b->rightheight;
1226 
1227  // move b
1228  avltreenode<valuetype> *p=c->parent;
1229  if (p) {
1230  if (p->right==c) {
1231  p->right=b;
1232  } else {
1233  p->left=b;
1234  }
1235  } else {
1236  #ifdef DEBUG_AVLTREE
1237  stdoutput.printf("(new tree top)\n\n");
1238  #endif
1239  *treetop=b;
1240  }
1241  b->parent=c->parent;
1242  b->right=c;
1243 
1244  // move c
1245  c->parent=b;
1246  c->left=star;
1247  c->leftheight=starheight;
1248 
1249  // move "star"
1250  if (star) {
1251  star->parent=c;
1252  }
1253 
1254  // update heights up the tree
1255  adjustParentHeights(c);
1256 
1257  // Since c was moved into a location in the tree that may not have
1258  // prevoiusly existed, and thus may have unbalanced the tree, we need
1259  // to continue balancing, starting at c.
1260  return c;
1261 }
1262 
1263 AVLTREE_TEMPLATE
1264 inline
1265 avltreenode<valuetype> *AVLTREENODE_CLASS::leftRightRotate(
1266  avltreenode<valuetype> **treetop) {
1267 
1268  /* one of these: (insert order c,a,b)
1269  *
1270  * \ \
1271  * c c
1272  * / \ / \ \
1273  * a -> b -> b
1274  * / \ / \ / \
1275  * b a a c
1276  * / \ / \ / \
1277  * * *
1278  *
1279  * needs left-right rotation */
1280 
1281  #ifdef DEBUG_AVLTREE
1282  stdoutput.printf("left-right rotation at ");
1283  node_print(value);
1284  stdoutput.printf(" {\n\n");
1285  stdoutput.printf("left part\n\n");
1286  #endif
1287 
1288  // do the left part of the left-right rotation...
1289 
1290  // get c, a, b, and "star"
1291  avltreenode<valuetype> *c=this;
1292  avltreenode<valuetype> *a=c->left;
1293  avltreenode<valuetype> *b=a->right;
1294  avltreenode<valuetype> *star=b->left;
1295  uint8_t starheight=b->leftheight;
1296 
1297  // move b
1298  c->left=b;
1299  b->parent=c;
1300  b->left=a;
1301 
1302  // move a
1303  a->parent=b;
1304  a->right=star;
1305  a->rightheight=starheight;
1306 
1307  // move "star"
1308  if (star) {
1309  star->parent=a;
1310  }
1311 
1312  // update heights up the tree
1313  adjustParentHeights(a);
1314 
1315  #ifdef DEBUG_AVLTREE
1316  avltreenode<valuetype> *top=this;
1317  while (top->parent) { top=top->parent; }
1318  top->print(); stdoutput.printf("\n");
1319  #endif
1320 
1321  // do the right part of the left-right rotation
1322  rightRotate(treetop);
1323 
1324  #ifdef DEBUG_AVLTREE
1325  stdoutput.printf("} left-right\n\n");
1326  #endif
1327 
1328  // Since a was moved into a location in the tree that may not have
1329  // prevoiusly existed, and thus may have unbalanced the tree, we need
1330  // to continue balancing, starting at a.
1331  return a;
1332 }
Definition: avltree.h:11
valuetype getValue() const
avltreenode< valuetype > * getPrevious()
avltreenode< valuetype > * getNext()
avltreenode< valuetype > * getRightChild()
avltreenode< valuetype > * getLeftChild()
int32_t compare(valuetype value) const
size_t printf(const char *format,...)