Rudiments: /home/dmuse/temp/rudiments/include/rudiments/private/avltreeinlines.h Source File

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 }
avltreenode
Definition: avltree.h:11
avltreenode::getValue
valuetype getValue() const
avltreenode::getPrevious
avltreenode< valuetype > * getPrevious()
avltreenode::getNext
avltreenode< valuetype > * getNext()
avltreenode::getRightChild
avltreenode< valuetype > * getRightChild()
avltreenode::getLeftChild
avltreenode< valuetype > * getLeftChild()
avltreenode::compare
int32_t compare(valuetype value) const
filedescriptor::printf
size_t printf(const char *format,...)