00001
00006
00007
00008
00009
00010
00011
00012
00013
00032 #include <assert.h>
00033 #include <ctype.h>
00034
00035 #include "CTB.hxx"
00036 #include "CTB_Trace.hxx"
00037 #include "CTBnum.hxx"
00038 #include "CTBosFill.hxx"
00039 #include "CTBprintf.hxx"
00040 #include "CTBbtree.hxx"
00041
00042
00044
00045 CTBbtree::~CTBbtree()
00046 {
00047 CTB_Trace("~CTBbtree()");
00048 Clear();
00049 }
00050
00051
00053
00060 void CTBbtree::Clear()
00061 {
00062 CTB_Trace("CTBbtree::Clear()");
00063 CTBbtreeNode* p_next = mp_rnode;
00064
00065 if (!p_next) return;
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 static const CTBuint32 status_childmask = CTBbtreeNode::status_childmask;
00077 static const CTBuint32 status_heavymask = CTBbtreeNode::status_heavymask;
00078
00079 for (;;) {
00080 CTBbtreeNode* p_cur = p_next;
00081
00082 assert(p_cur->mp_head == this);
00083
00084 assert((p_cur->mi_status & status_childmask) != status_childmask);
00085
00086 assert((p_cur->mi_status & status_heavymask) != status_heavymask);
00087
00088 assert(!p_cur->mp_up || (p_cur->mi_status & status_childmask));
00089
00090 assert(!p_cur->IsLeftChild() || p_cur->mp_up->mp_left==p_cur);
00091
00092 assert(!p_cur->IsRightChild() || p_cur->mp_up->mp_right==p_cur);
00093
00094 assert(!p_cur->mp_left || p_cur->mp_left->mp_up==p_cur);
00095
00096 assert(!p_cur->mp_right || p_cur->mp_right->mp_up==p_cur);
00097
00098 p_next = p_cur->mp_left;
00099 if (p_next) continue;
00100
00101 p_next = p_cur->mp_right;
00102 if (p_next) continue;
00103
00104 p_next = p_cur->mp_up;
00105
00106 if (p_cur->IsLeftChild()) p_next->mp_left = 0;
00107 if (p_cur->IsRightChild()) p_next->mp_right = 0;
00108 p_cur->mp_head = 0;
00109 delete p_cur;
00110
00111 if (!p_next) break;
00112 }
00113
00114 mp_rnode = 0;
00115 mp_first = 0;
00116 mp_last = 0;
00117 mi_size = 0;
00118
00119 return;
00120 }
00121
00122
00124
00132 void CTBbtree::TreeHeight(int& i_minh, int& i_maxh, float& f_avrp) const
00133 {
00134 double d_nnode;
00135 double d_ncomp;
00136
00137 if (!mp_rnode) {
00138 i_minh = 0;
00139 i_maxh = 0;
00140 f_avrp = 0.;
00141 return;
00142 }
00143
00144 mp_rnode->SubTreeHeight(i_minh,i_maxh,d_nnode,d_ncomp);
00145 f_avrp = d_ncomp/d_nnode;
00146 return;
00147 }
00148
00149
00151
00157 bool CTBbtree::TreeCheck(ostream* p_os) const
00158 {
00159 int i_maxh = 0;
00160
00161 return (mp_rnode) ? mp_rnode->SubTreeCheck(p_os,i_maxh) : true;
00162 }
00163
00164
00165 void print_address(
00166 ostream& os,
00167 void* p)
00168 {
00169 if (p) os << CTBprintf((CTBuint32) p,"x",8);
00170 else os << " -";
00171 return;
00172 }
00173
00174
00176
00200 void CTBbtree::Dump(int i_indent, ostream& os, const char* p_text) const
00201 {
00202 CTBosFill bl(i_indent);
00203 int i_minh = 0;
00204 int i_maxh = 0;
00205 float f_avrp = 0.;
00206
00207 os << bl << "--CTBbtree ";
00208 if (p_text) os << p_text;
00209 os << " @ " << this << endl;
00210 os << bl << " mp_rnode: " << mp_rnode << "\n";
00211 os << bl << " mp_first: " << mp_first << "\n";
00212 os << bl << " mp_last: " << mp_last << "\n";
00213 os << bl << " mi_size: " << mi_size << "\n";
00214
00215 if (!mp_rnode) return;
00216
00217 TreeHeight(i_minh,i_maxh,f_avrp);
00218 os << bl << " tree height max: " << i_maxh
00219 << " min: " << i_minh
00220 << " average path: " << CTBprintf(f_avrp,"f",6,2) << "\n";
00221
00222 os << bl <<" rank lvl bc this up left right location\n";
00223
00224 for (CTBbtreeNode* p_cur = mp_first; p_cur; p_cur = p_cur->Next()) {
00225 CTBint i_rank = p_cur->LWeight();
00226 int i_lvl = 0;
00227 char c_bmode;
00228 char c_cmode;
00229
00230
00231
00232
00233 for (CTBbtreeNode* p = p_cur; p; p = p->mp_up) {
00234 i_lvl += 1;
00235 if (p->IsRightChild()) i_rank += p->mp_up->LWeight();
00236 }
00237
00238 os << bl << CTBprintf(i_rank-1,"d",6)
00239 << " " << CTBprintf(i_lvl,"d",3);
00240
00241 c_bmode = '0';
00242 if (p_cur->IsLeftHeavy()) c_bmode = '-';
00243 if (p_cur->IsRightHeavy()) c_bmode = '+';
00244 c_cmode = '^';
00245 if (p_cur->IsLeftChild()) c_cmode = 'l';
00246 if (p_cur->IsRightChild()) c_cmode = 'r';
00247 os << " " << c_bmode << c_cmode;;
00248
00249 os << " "; print_address(os,p_cur);
00250 os << " "; print_address(os,p_cur->mp_up);
00251 os << " "; print_address(os,p_cur->mp_left);
00252 os << " "; print_address(os,p_cur->mp_right);
00253
00254 i_lvl = 0;
00255 os << " ";
00256 for (CTBbtreeNode* p = p_cur; p; p = p->mp_up) {
00257 char c_cmode = '^';
00258
00259 if (p->IsLeftChild()) c_cmode = 'l';
00260 if (p->IsRightChild()) c_cmode = 'r';
00261 if (!p->mp_left && !p->mp_right) c_cmode = toupper(c_cmode);
00262
00263 os << c_cmode;
00264 i_lvl += 1;
00265 if (i_lvl >= 24-i_indent) {
00266 os << ">";
00267 break;
00268 }
00269 }
00270 os << endl;
00271 }
00272
00273 TreeCheck(&cerr);
00274
00275 return;
00276 }
00277
00283
00285
00290 CTBbtreeNode* CTBbtree::operator[](CTBint i_ind) const
00291 {
00292 CTB_Trace("CTBbtree::operator[](CTBint)");
00293 CTBint i_rel = i_ind + 1;
00294
00295 for (CTBbtreeNode* p = mp_rnode; p; ) {
00296 CTBint i_lw = p->LWeight();
00297
00298 if (i_rel == i_lw) return p;
00299 if (i_rel < i_lw) {
00300 p = p->mp_left;
00301 } else {
00302 i_rel -= i_lw;
00303 p = p->mp_right;
00304 }
00305 }
00306
00307 return 0;
00308 }
00309
00310
00312
00321 CTBbtree& CTBbtree::operator=(const CTBbtree& rhs)
00322 {
00323
00324
00325
00326 CTB_Trace("CTBbtree::operator=(const CTBbtree&)");
00327 CTBbtreeNode* p_rpos = rhs.mp_rnode;
00328 CTBbtreeNode* p_rpar = 0;
00329 CTBbtreeNode* p_lpos = 0;
00330 CTBbtreeNode* p_lpar = 0;
00331 int i_origin = 0;
00332
00333
00334 if (&rhs == this) return *this;
00335
00336 Clear();
00337
00338 if (!p_rpos) return *this;
00339
00340 for (;;) {
00341 if (i_origin == 0) {
00342
00343 p_lpos = p_rpos->Clone();
00344
00345 p_lpos->mp_head = this;
00346 p_lpos->mi_status = p_rpos->mi_status;
00347 if(p_rpos->IsRNode()) {
00348 mp_rnode = p_lpos;
00349 }
00350 else if (p_rpos->IsLeftChild()) {
00351 p_lpar->mp_left = p_lpos;
00352 p_lpos->mp_up = p_lpar;
00353 } else {
00354 p_lpar->mp_right = p_lpos;
00355 p_lpos->mp_up = p_lpar;
00356 }
00357
00358 if (p_rpos->mp_left) {
00359 i_origin = 0;
00360 p_rpar = p_rpos;
00361 p_rpos = p_rpos->mp_left;
00362 p_lpar = p_lpos;
00363 p_lpos = 0;
00364 continue;
00365 } else {
00366 i_origin = -1;
00367 }
00368 }
00369
00370 if (i_origin == -1 && p_rpos->mp_right) {
00371 i_origin = 0;
00372 p_rpar = p_rpos;
00373 p_rpos = p_rpos->mp_right;
00374 p_lpar = p_lpos;
00375 p_lpos = 0;
00376 continue;
00377 }
00378
00379 if (p_rpos->IsRNode()) break;
00380
00381 i_origin = (p_rpos->IsLeftChild()) ? -1 : 1;
00382 p_rpos = p_rpar;
00383 p_rpar = p_rpos->mp_up;
00384 p_lpos = p_lpar;
00385 p_lpar = p_lpos->mp_up;
00386 }
00387
00388 mp_first = mp_rnode;
00389 mp_last = mp_rnode;
00390 while (mp_first->mp_left) mp_first = mp_first->mp_left;
00391 while (mp_last->mp_right) mp_last = mp_last->mp_right;
00392
00393 return *this;
00394 }
00395
00396
00398
00399 CTBbtreeNode::~CTBbtreeNode()
00400 {
00401 CTB_Trace("~CTBbtreeNode()");
00402
00403 if (mp_head) Remove();
00404 }
00405
00406
00408
00418 CTBbtreeNode* CTBbtreeNode::Clone() const
00419 {
00420 CTB_Trace("CTBbtreeNode::Clone()");
00421
00422 return new CTBbtreeNode();
00423 }
00424
00425
00427
00428 CTBbtreeNode* CTBbtreeNode::Next() const
00429 {
00430 CTB_Trace("CTBbtreeNode::Next()");
00431 CTBbtreeNode* p_next;
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441 if (mp_right) {
00442 p_next = mp_right;
00443 while (p_next->mp_left) p_next = p_next->mp_left;
00444 return p_next;
00445 }
00446
00447
00448
00449
00450
00451
00452
00453 p_next = (CTBbtreeNode*) this;
00454 while (p_next->IsRightChild()) p_next = p_next->mp_up;
00455 return p_next->mp_up;
00456 }
00457
00458
00460
00461 CTBbtreeNode* CTBbtreeNode::Prev() const
00462 {
00463 CTB_Trace("CTBbtreeNode::Prev()");
00464 CTBbtreeNode* p_prev;
00465
00466
00467
00468
00469
00470
00471 if (mp_left) {
00472 p_prev = mp_left;
00473 while (p_prev->mp_right) p_prev = p_prev->mp_right;
00474 return p_prev;
00475 }
00476
00477
00478
00479
00480
00481
00482
00483 p_prev = (CTBbtreeNode*) this;
00484 while(p_prev->IsLeftChild()) p_prev = p_prev->mp_up;
00485 return p_prev->mp_up;
00486 }
00487
00488
00490
00499 CTBbtreeNode* CTBbtreeNode::Skip(CTBint i_offset) const
00500 {
00501 CTB_Trace("CTBbtreeNode::Skip(CTBint)");
00502 CTBbtreeNode* p = (CTBbtreeNode*) this;
00503 CTBint i_rel = LWeight() + i_offset;
00504
00505 if (i_offset == 0) return p;
00506 if (i_offset == 1) return Next();
00507 if (i_offset == -1) return Prev();
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520 for (; p; p = p->mp_up) {
00521 if (i_offset < 0) {
00522 if (i_rel >= 1) break;
00523 } else {
00524 if (p->IsLeftChild() && i_rel <= p->mp_up->LWeight() - 1) break;
00525 if (p->IsRNode() && i_rel <= mp_head->Size()) break;
00526 }
00527 if (p->IsRightChild()) {
00528 i_rel += p->mp_up->LWeight();
00529 }
00530 }
00531
00532
00533
00534 while (p) {
00535 CTBint i_lw = p->LWeight();
00536
00537 if (i_rel == i_lw) return p;
00538 if (i_rel < i_lw) {
00539 p = p->mp_left;
00540 } else {
00541 i_rel -= i_lw;
00542 p = p->mp_right;
00543 }
00544 }
00545
00546 return 0;
00547 }
00548
00549
00551
00552 CTBint CTBbtreeNode::Rank() const
00553 {
00554 CTB_Trace("CTBbtreeNode::Rank()");
00555 CTBint i_rank = LWeight();
00556
00557 for (const CTBbtreeNode* p = this; p; p = p->mp_up) {
00558 if (p->IsRightChild()) i_rank += p->mp_up->LWeight();
00559 }
00560
00561 return i_rank-1;
00562 }
00563
00564
00566
00573 void CTBbtreeNode::Insert(CTBbtree& head,CTBbtreeNode* p_parent,int i_ctype)
00574 {
00575 CTB_Trace("CTBbtreeNode::Insert(CTBbtree&,CTBbtreeNode*,int)");
00576
00577 assert(!mp_head);
00578
00579 if (!p_parent) {
00580 assert(i_ctype==0);
00581 assert(!head.mp_rnode);
00582
00583 head.mi_size += 1;
00584 head.mp_rnode = this;
00585 head.mp_first = this;
00586 head.mp_last = this;
00587
00588 mp_head = &head;
00589 mp_up = 0;
00590 mp_left = 0;
00591 mp_right = 0;
00592 mi_status = status_deltaw;
00593
00594 } else {
00595 assert(i_ctype!=0);
00596 assert(p_parent->mp_head==&head);
00597 assert(!((i_ctype<0) ?
00598 p_parent->mp_left : p_parent->mp_right));
00599
00600 head.mi_size += 1;
00601 mp_head = &head;
00602 mp_up = p_parent;
00603 mp_left = 0;
00604 mp_right = 0;
00605 if (i_ctype < 0) {
00606 p_parent->mp_left = this;
00607 mi_status = status_lchild + status_deltaw;
00608 if (head.mp_first == p_parent) head.mp_first = this;
00609 } else {
00610 p_parent->mp_right = this;
00611 mi_status = status_rchild + status_deltaw;
00612 if (head.mp_last == p_parent) head.mp_last = this;
00613 }
00614 }
00615
00616 InsertFixup();
00617
00618 return;
00619 }
00620
00621
00623
00634 void CTBbtreeNode::Remove()
00635 {
00636 CTB_Trace("CTBbtreeNode::Remove()");
00637
00638 assert(mp_head);
00639
00640
00641 assert((mi_status & status_childmask) != status_childmask);
00642
00643 assert((mi_status & status_heavymask) != status_heavymask);
00644
00645 assert(!mp_up || (mi_status & status_childmask));
00646
00647 assert(!IsLeftChild() || mp_up->mp_left==this);
00648
00649 assert(!IsRightChild() || mp_up->mp_right==this);
00650
00651 assert(!mp_left || mp_left->mp_up==this);
00652
00653 assert(!mp_right || mp_right->mp_up==this);
00654
00655 if (mp_left && mp_right) {
00656 CTBbtreeNode* p_next = Next();
00657
00658 p_next->Remove();
00659
00660 p_next->mp_head = mp_head;
00661 p_next->mp_up = mp_up;
00662 p_next->mp_left = mp_left;
00663 p_next->mp_right = mp_right;
00664 p_next->mi_status = mi_status;
00665 if (IsRNode()) mp_head->mp_rnode = p_next;
00666 else if (IsLeftChild()) mp_up->mp_left = p_next;
00667 else mp_up->mp_right = p_next;
00668 if (mp_left) mp_left->mp_up = p_next;
00669 if (mp_right) mp_right->mp_up = p_next;
00670
00671 if (mp_head->mp_first == this) mp_head->mp_first = p_next;
00672 if (mp_head->mp_last == this) mp_head->mp_last = p_next;
00673
00674 } else {
00675 CTBbtreeNode* p_sub = (mp_left) ? mp_left : mp_right;
00676
00677 RemoveFixup();
00678
00679 mp_head->mi_size -= 1;
00680 if (mp_head->mp_first == this) mp_head->mp_first = Next();
00681 if (mp_head->mp_last == this) mp_head->mp_last = Prev();
00682
00683 if (p_sub) {
00684 p_sub->mp_up = mp_up;
00685 p_sub->mi_status &= ~status_childmask;
00686 p_sub->mi_status |= mi_status & status_childmask;
00687 }
00688
00689 if (IsRNode()) mp_head->mp_rnode = p_sub;
00690 else if (IsLeftChild()) mp_up->mp_left = p_sub;
00691 else mp_up->mp_right = p_sub;
00692 }
00693
00694 mp_head = 0;
00695 mp_up = 0;
00696 mp_left = 0;
00697 mp_right = 0;
00698 mi_status = 0;
00699
00700 return;
00701 }
00702
00703
00705
00719 void CTBbtreeNode::RotateLeft()
00720 {
00721 CTB_Trace("CTBbtreeNode::RotateLeft()");
00722
00723 assert(mp_head);
00724 assert(mp_right);
00725
00726 CTBbtreeNode* p_b = this;
00727 CTBbtreeNode* p_c = mp_right;
00728 CTBbtreeNode* p_b_up = mp_up;
00729 CTBbtreeNode* p_ga = p_c->mp_left;
00730
00731 p_c->mp_up = p_b_up;
00732 p_c->mi_status &= ~status_childmask;
00733 p_c->mi_status |= p_b->mi_status & status_childmask;
00734
00735 if (p_b->IsRNode()) mp_head->mp_rnode = p_c;
00736 else if (p_b->IsLeftChild()) p_b_up->mp_left = p_c;
00737 else p_b_up->mp_right = p_c;
00738
00739 p_b->mp_up = p_c;
00740 p_b->SetLeftChild();
00741
00742 p_c->mp_left = p_b;
00743
00744 if (p_ga) {
00745 p_ga->mp_up = p_b;
00746 p_ga->SetRightChild();
00747 }
00748
00749 p_b->mp_right = p_ga;
00750
00751 p_c->LWeight(p_c->LWeight() + p_b->LWeight());
00752
00753 return;
00754 }
00755
00756
00757
00758
00759
00760
00761
00763
00778 void CTBbtreeNode::RotateRight()
00779 {
00780 CTB_Trace("CTBbtreeNode::RotateRight()");
00781
00782 assert(mp_head);
00783 assert(mp_left);
00784
00785 CTBbtreeNode* p_b = this;
00786 CTBbtreeNode* p_a = mp_left;
00787 CTBbtreeNode* p_b_up = mp_up;
00788 CTBbtreeNode* p_be = p_a->mp_right;
00789
00790 p_a->mp_up = p_b_up;
00791 p_a->mi_status &= ~status_childmask;
00792 p_a->mi_status |= p_b->mi_status & status_childmask;
00793
00794 if (p_b->IsRNode()) mp_head->mp_rnode = p_a;
00795 else if (p_b->IsLeftChild()) p_b_up->mp_left = p_a;
00796 else p_b_up->mp_right = p_a;
00797
00798 p_b->mp_up = p_a;
00799 p_b->SetRightChild();
00800
00801 p_a->mp_right = p_b;
00802
00803 if (p_be) {
00804 p_be->mp_up = p_b;
00805 p_be->SetLeftChild();
00806 }
00807
00808 p_b->mp_left = p_be;
00809
00810 p_b->LWeight(p_b->LWeight() - p_a->LWeight());
00811
00812 return;
00813 }
00814
00815
00817
00834 void CTBbtreeNode::RotateLeftRight()
00835 {
00836 CTB_Trace("CTBbtreeNode::RotateLeftRight()");
00837
00838 assert(mp_left);
00839 assert(mp_left->mp_right);
00840
00841 mp_left->RotateLeft();
00842 RotateRight();
00843
00844 return;
00845 }
00846
00847
00849
00866 void CTBbtreeNode::RotateRightLeft()
00867 {
00868 CTB_Trace("CTBbtreeNode::RotateRightLeft()");
00869
00870 assert(mp_right);
00871 assert(mp_right->mp_left);
00872
00873 mp_right->RotateRight();
00874 RotateLeft();
00875
00876 return;
00877 }
00878
00879
00881
00882 void CTBbtreeNode::InsertFixup()
00883 {
00884
00885
00886
00887
00888
00889
00890
00891 CTB_Trace("CTBbtreeNode::InsertFixup()");
00892
00893 for (CTBbtreeNode* p = this; p; p = p->mp_up) {
00894 if (p->IsLeftChild()) p->mp_up->IncLWeight();
00895 }
00896
00897 #ifndef UNBALANCED
00898
00899 for (CTBbtreeNode* p_b = this; ; ) {
00900 CTBbtreeNode* p_a = p_b->mp_up;
00901
00902 if (!p_a) break;
00903
00904 if (p_b->IsRightChild()) {
00905 if (p_a->IsLeftHeavy()) {
00906 p_a->SetBalanced();
00907 break;
00908 }
00909 if (p_a->IsBalanced()) {
00910 p_a->SetRightHeavy();
00911
00912 } else {
00913 assert(!(p_b->IsBalanced()));
00914
00915 if (p_b->IsRightHeavy()) {
00916 p_a->RotateLeft();
00917 p_b->SetBalanced();
00918 p_a->SetBalanced();
00919 break;
00920
00921 } else {
00922 CTBbtreeNode* p_x = p_b->mp_left;
00923
00924 assert(p_x);
00925 p_a->RotateRightLeft();
00926 p_b->SetBalanced();
00927 p_a->SetBalanced();
00928 if (p_x->IsRightHeavy()) p_a->SetLeftHeavy();
00929 if (p_x->IsLeftHeavy()) p_b->SetRightHeavy();
00930 p_x->SetBalanced();
00931 break;
00932 }
00933 }
00934
00935 } else {
00936 if (p_a->IsRightHeavy()) {
00937 p_a->SetBalanced();
00938 break;
00939 }
00940 if (p_a->IsBalanced()) {
00941 p_a->SetLeftHeavy();
00942
00943 } else {
00944 assert(!(p_b->IsBalanced()));
00945
00946 if (p_b->IsLeftHeavy()) {
00947 p_a->RotateRight();
00948 p_b->SetBalanced();
00949 p_a->SetBalanced();
00950 break;
00951
00952 } else {
00953 CTBbtreeNode* p_x = p_b->mp_right;
00954
00955 assert(p_x);
00956 p_a->RotateLeftRight();
00957 p_b->SetBalanced();
00958 p_a->SetBalanced();
00959 if (p_x->IsLeftHeavy()) p_a->SetRightHeavy();
00960 if (p_x->IsRightHeavy()) p_b->SetLeftHeavy();
00961 p_x->SetBalanced();
00962 break;
00963 }
00964 }
00965 }
00966
00967 p_b = p_a;
00968 }
00969
00970 #endif
00971
00972 return;
00973 }
00974
00975
00977
00978 void CTBbtreeNode::RemoveFixup()
00979 {
00980
00981
00982
00983
00984
00985
00986 CTB_Trace("CTBbtreeNode::RemoveFixup()");
00987
00988 for (CTBbtreeNode* p = this; p; p = p->mp_up) {
00989 if (p->IsLeftChild()) p->mp_up->DecLWeight();
00990 }
00991
00992 #ifndef UNBALANCED
00993
00994 for (CTBbtreeNode* p = this; ; ) {
00995 CTBbtreeNode* p_a = p->mp_up;
00996 CTBbtreeNode* p_next = p_a;
00997
00998 if (!p_a) break;
00999
01000 if (p->IsLeftChild()) {
01001 if (p_a->IsLeftHeavy()) {
01002 p_a->SetBalanced();
01003
01004 } else if (p_a->IsBalanced()) {
01005 p_a->SetRightHeavy();
01006 break;
01007
01008 } else {
01009 CTBbtreeNode* p_b = p_a->mp_right;
01010
01011 assert(p_b);
01012 if (p_b->IsBalanced()) {
01013 p_a->RotateLeft();
01014 p_b->SetLeftHeavy();
01015 break;
01016
01017 } else if (p_b->IsRightHeavy()) {
01018 p_a->RotateLeft();
01019 p_a->SetBalanced();
01020 p_b->SetBalanced();
01021 p_next = p_b;
01022
01023 } else {
01024 CTBbtreeNode* p_x = p_b->mp_left;
01025
01026 assert(p_x);
01027 p_a->RotateRightLeft();
01028 p_a->SetBalanced();
01029 p_b->SetBalanced();
01030 if (p_x->IsRightHeavy()) p_a->SetLeftHeavy();
01031 if (p_x->IsLeftHeavy()) p_b->SetRightHeavy();
01032 p_x->SetBalanced();
01033 p_next = p_x;
01034 }
01035 }
01036
01037 } else {
01038 if (p_a->IsRightHeavy()) {
01039 p_a->SetBalanced();
01040
01041 } else if (p_a->IsBalanced()) {
01042 p_a->SetLeftHeavy();
01043 break;
01044
01045 } else {
01046 CTBbtreeNode* p_b = p_a->mp_left;
01047
01048 assert(p_b);
01049 if (p_b->IsBalanced()) {
01050 p_a->RotateRight();
01051 p_b->SetRightHeavy();
01052 break;
01053
01054 } else if (p_b->IsLeftHeavy()) {
01055 p_a->RotateRight();
01056 p_a->SetBalanced();
01057 p_b->SetBalanced();
01058 p_next = p_b;
01059
01060 } else {
01061 CTBbtreeNode* p_x = p_b->mp_right;
01062
01063 assert(p_x);
01064 p_a->RotateLeftRight();
01065 p_a->SetBalanced();
01066 p_b->SetBalanced();
01067 if (p_x->IsLeftHeavy()) p_a->SetRightHeavy();
01068 if (p_x->IsRightHeavy()) p_b->SetLeftHeavy();
01069 p_x->SetBalanced();
01070 p_next = p_x;
01071 }
01072 }
01073
01074 }
01075
01076 p = p_next;
01077 }
01078
01079 #endif
01080
01081 return;
01082 }
01083
01084
01086
01094 void CTBbtreeNode::SubTreeHeight(int& i_minh, int& i_maxh,
01095 double& d_nnode, double& d_ncomp) const
01096 {
01097 int i_minh_l;
01098 int i_maxh_l = 0;
01099 double d_nnode_l;
01100 double d_ncomp_l;
01101 int i_minh_r;
01102 int i_maxh_r = 0;
01103 double d_nnode_r;
01104 double d_ncomp_r;
01105
01106 if (!mp_left && !mp_right) {
01107 i_minh = 1;
01108 i_maxh = 1;
01109 d_nnode = 1.;
01110 d_ncomp = 1.;
01111 return;
01112 }
01113
01114 if (mp_left) mp_left ->SubTreeHeight(i_minh_l,i_maxh_l,d_nnode_l,d_ncomp_l);
01115 if (mp_right) mp_right->SubTreeHeight(i_minh_r,i_maxh_r,d_nnode_r,d_ncomp_r);
01116
01117 if (mp_left && !mp_right) {
01118 i_minh = 1 + i_minh_l;
01119 i_maxh = 1 + i_maxh_l;
01120 d_nnode = 1. + d_nnode_l;
01121 d_ncomp = d_nnode + d_ncomp_l;
01122 } else if (!mp_left && mp_right) {
01123 i_minh = 1 + i_minh_r;
01124 i_maxh = 1 + i_maxh_r;
01125 d_nnode = 1. + d_nnode_r;
01126 d_ncomp = d_nnode + d_ncomp_r;
01127 } else {
01128 i_minh = 1 + CTBmin(i_minh_l,i_minh_r);
01129 i_maxh = 1 + CTBmax(i_maxh_l,i_maxh_r);
01130 d_nnode = 1. + d_nnode_l + d_nnode_r;
01131 d_ncomp = d_nnode + d_ncomp_l + d_ncomp_r;
01132 }
01133
01134 return;
01135 }
01136
01137
01139
01140 bool CTBbtreeNode::SubTreeCheck(
01141 ostream* p_os,
01142 int& i_maxh) const
01143 {
01144 bool b_ok_l = true;
01145 bool b_ok_r = true;
01146 bool b_ok;
01147 int i_maxh_l = 0;
01148 int i_maxh_r = 0;
01149 int i_dheight;
01150
01151 if (!mp_left && !mp_right) {
01152 i_maxh = 1;
01153 return true;
01154 }
01155
01156 if (mp_left) b_ok_l = mp_left ->SubTreeCheck(p_os,i_maxh_l);
01157 if (mp_right) b_ok_r = mp_right->SubTreeCheck(p_os,i_maxh_r);
01158
01159 b_ok = b_ok_l && b_ok_r;
01160 i_maxh = 1 + CTBmax(i_maxh_l,i_maxh_r);
01161
01162 i_dheight = i_maxh_r - i_maxh_l;
01163
01164 if (IsBalanced() && i_dheight != 0) {
01165 b_ok = false;
01166 if (p_os) (*p_os) << "%CTBbtreeNode-I Node @" << (void*) this
01167 << " status = balanced but h_r-h_r = "
01168 << i_dheight << endl;
01169 }
01170 if (IsLeftHeavy() && i_dheight != -1) {
01171 b_ok = false;
01172 if (p_os) (*p_os) << "%CTBbtreeNode-I Node @" << (void*) this
01173 << " status = leftheavy but h_r-h_r = "
01174 << i_dheight << endl;
01175 }
01176 if (IsRightHeavy() && i_dheight != 1) {
01177 b_ok = false;
01178 if (p_os) (*p_os) << "%CTBbtreeNode-I Node @" << (void*) this
01179 << " status = rightheavy but h_r-h_r = "
01180 << i_dheight << endl;
01181 }
01182
01183 return b_ok;
01184 }