TBtree.cxx

Go to the documentation of this file.
00001 // @(#)root/cont:$Id: TBtree.cxx 23529 2008-04-24 16:21:02Z rdm $
00002 // Author: Fons Rademakers   10/10/95
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      //
00014 // TBtree                                                               //
00015 //                                                                      //
00016 // B-tree class. TBtree inherits from the TSeqCollection ABC.           //
00017 //                                                                      //
00018 //////////////////////////////////////////////////////////////////////////
00019 //BEGIN_HTML <!--
00020 /* -->
00021 <h2>B-tree Implementation notes</h2>
00022 
00023 This implements B-trees with several refinements. Most of them can be found
00024 in Knuth Vol 3, but some were developed to adapt to restrictions imposed
00025 by C++. First, a restatement of Knuth's properties that a B-tree must
00026 satisfy, assuming we make the enhancement he suggests in the paragraph
00027 at the bottom of page 476. Instead of storing null pointers to non-existent
00028 nodes (which Knuth calls the leaves) we utilize the space to store keys.
00029 Therefore, what Knuth calls level (l-1) is the bottom of our tree, and
00030 we call the nodes at this level LeafNodes. Other nodes are called InnerNodes.
00031 The other enhancement we have adopted is in the paragraph at the bottom of
00032 page 477: overflow control.
00033 <p>
00034 The following are modifications of Knuth's properties on page 478:
00035 <p>
00036 <ol>
00037 <li>  Every InnerNode has at most Order keys, and at most Order+1 sub-trees.
00038 <li>  Every LeafNode has at most 2*(Order+1) keys.
00039 <li>  An InnerNode with k keys has k+1 sub-trees.
00040 <li>  Every InnerNode that is not the root has at least InnerLowWaterMark keys.
00041 <li>  Every LeafNode that is not the root has at least LeafLowWaterMark keys.
00042 <li>  If the root is a LeafNode, it has at least one key.
00043 <li>  If the root is an InnerNode, it has at least one key and two sub-trees.
00044 <li>  All LeafNodes are the same distance from the root as all the other
00045       LeafNodes.
00046 <li>  For InnerNode n with key n[i].key, then sub-tree n[i-1].tree contains
00047       all keys &lt; n[i].key, and sub-tree n[i].tree contains all keys
00048       &gt;= n[i].key.
00049 <li>  Order is at least 3.
00050 </ol>
00051 <p>
00052 The values of InnerLowWaterMark and LeafLowWaterMark may actually be set
00053 by the user when the tree is initialized, but currently they are set
00054 automatically to:
00055 <p><pre>
00056         InnerLowWaterMark = ceiling(Order/2)
00057         LeafLowWaterMark  = Order - 1
00058 </pre><p>
00059 If the tree is only filled, then all the nodes will be at least 2/3 full.
00060 They will almost all be exactly 2/3 full if the elements are added to the
00061 tree in order (either increasing or decreasing). [Knuth says McCreight's
00062 experiments showed almost 100% memory utilization. I don't see how that
00063 can be given the algorithms that Knuth gives. McCreight must have used
00064 a different scheme for balancing. [No, he used a different scheme for
00065 splitting: he did a two-way split instead of the three way split as we do
00066 here. Which means that McCreight does better on insertion of ordered data,
00067 but we should do better on insertion of random data.]]
00068 <p>
00069 It must also be noted that B-trees were designed for DISK access algorithms,
00070 not necessarily in-memory sorting, as we intend it to be used here. However,
00071 if the order is kept small (&lt; 6?) any inefficiency is negligible for
00072 in-memory sorting. Knuth points out that balanced trees are actually
00073 preferable for memory sorting. I'm not sure that I believe this, but
00074 it's interesting. Also, deleting elements from balanced binary trees, being
00075 beyond the scope of Knuth's book (p. 465), is beyond my scope. B-trees
00076 are good enough.
00077 <p>
00078 A B-tree is declared to be of a certain ORDER (3 by default). This number
00079 determines the number of keys contained in any interior node of the tree.
00080 Each interior node will contain ORDER keys, and therefore ORDER+1 pointers
00081 to sub-trees. The keys are numbered and indexed 1 to ORDER while the
00082 pointers are numbered and indexed 0 to ORDER. The 0th ptr points to the
00083 sub-tree of all elements that are less than key[1]. Ptr[1] points to the
00084 sub-tree that contains all the elements greater than key[1] and less than
00085 key[2]. etc. The array of pointers and keys is allocated as ORDER+1
00086 pairs of keys and nodes, meaning that one key field (key[0]) is not used
00087 and therefore wasted.  Given that the number of interior nodes is
00088 small, that this waste allows fewer cases of special code, and that it
00089 is useful in certain of the methods, it was felt to be a worthwhile waste.
00090 <p>
00091 The size of the exterior nodes (leaf nodes) does not need to be related to
00092 the size of the interior nodes at all. Since leaf nodes contain only
00093 keys, they may be as large or small as we like independent of the size
00094 of the interior nodes. For no particular reason other than it seems like
00095 a good idea, we will allocate 2*(ORDER+1) keys in each leaf node, and they
00096 will be numbered and indexed from 0 to 2*ORDER+1. It does have the advantage
00097 of keeping the size of the leaf and interior arrays the same, so that if we
00098 find allocation and de-allocation of these arrays expensive, we can modify
00099 their allocation to use a garbage ring, or something.
00100 <p>
00101 Both of these numbers will be run-time constants associated with each tree
00102 (each tree at run-time can be of a different order). The variable "order"
00103 is the order of the tree, and the inclusive upper limit on the indices of
00104 the keys in the interior nodes.  The variable "order2" is the inclusive
00105 upper limit on the indices of the leaf nodes, and is designed
00106 <p><pre>
00107     (1) to keep the sizes of the two kinds of nodes the same;
00108     (2) to keep the expressions involving the arrays of keys looking
00109         somewhat the same:   lower limit        upper limit
00110           for inner nodes:        1                order
00111           for leaf  nodes:        0                order2
00112         Remember that index 0 of the inner nodes is special.
00113 </pre><p>
00114 Currently, order2 = 2*(order+1).
00115 <p><pre>
00116  Picture: (also see Knuth Vol 3 pg 478)
00117 
00118            +--+--+--+--+--+--...
00119            |  |  |  |  |  |
00120  parent---&gt;|  |     |     |
00121            |  |     |     |
00122            +*-+*-+*-+--+--+--...
00123             |  |  |
00124        +----+  |  +-----+
00125        |       +-----+  |
00126        V             |  V
00127        +----------+  |  +----------+
00128        |          |  |  |          |
00129  this-&gt;|          |  |  |          |&lt;--sib
00130        +----------+  |  +----------+
00131                      V
00132                     data
00133 </pre><p>
00134 It is conceptually VERY convenient to think of the data as being the
00135 very first element of the sib node. Any primitive that tells sib to
00136 perform some action on n nodes should include this 'hidden' element.
00137 For InnerNodes, the hidden element has (physical) index 0 in the array,
00138 and in LeafNodes, the hidden element has (virtual) index -1 in the array.
00139 Therefore, there are two 'size' primitives for nodes:
00140 <p><pre>
00141 Psize       - the physical size: how many elements are contained in the
00142               array in the node.
00143 Vsize       - the 'virtual' size; if the node is pointed to by
00144               element 0 of the parent node, then Vsize == Psize;
00145               otherwise the element in the parent item that points to this
00146               node 'belongs' to this node, and Vsize == Psize+1;
00147 </pre><p>
00148 Parent nodes are always InnerNodes.
00149 <p>
00150 These are the primitive operations on Nodes:
00151 <p><pre>
00152 Append(elt)     - adds an element to the end of the array of elements in a
00153                   node.  It must never be called where appending the element
00154                   would fill the node.
00155 Split()         - divide a node in two, and create two new nodes.
00156 SplitWith(sib)  - create a third node between this node and the sib node,
00157                   divvying up the elements of their arrays.
00158 PushLeft(n)     - move n elements into the left sibling
00159 PushRight(n)    - move n elements into the right sibling
00160 BalanceWithRight() - even up the number of elements in the two nodes.
00161 BalanceWithLeft()  - ditto
00162 </pre><p>
00163 To allow this implementation of btrees to also be an implementation of
00164 sorted arrays/lists, the overhead is included to allow O(log n) access
00165 of elements by their rank (`give me the 5th largest element').
00166 Therefore, each Item keeps track of the number of keys in and below it
00167 in the tree (remember, each item's tree is all keys to the RIGHT of the
00168 item's own key).
00169 <p><pre>
00170 [ [ &lt; 0 1 2 3 &gt; 4 &lt; 5 6 7 &gt; 8 &lt; 9 10 11 12 &gt; ] 13 [ &lt; 14 15 16 &gt; 17 &lt; 18 19 20 &gt; ] ]
00171    4  1 1 1 1   4   1 1 1   5   1  1  1  1      7  3   1  1  1    4    1  1  1
00172 </pre><p>
00173 <!--*/
00174 // -->END_HTML
00175 
00176 #include <stdlib.h>
00177 #include "TBtree.h"
00178 
00179 
00180 ClassImp(TBtree)
00181 
00182 //______________________________________________________________________________
00183 TBtree::TBtree(int order)
00184 {
00185    // Create a B-tree of certain order (by default 3).
00186 
00187    Init(order);
00188 }
00189 
00190 //______________________________________________________________________________
00191 TBtree::~TBtree()
00192 {
00193    // Delete B-tree. Objects are not deleted unless the TBtree is the
00194    // owner (set via SetOwner()).
00195 
00196    if (fRoot) {
00197       Clear();
00198       SafeDelete(fRoot);
00199    }
00200 }
00201 
00202 //______________________________________________________________________________
00203 void TBtree::Add(TObject *obj)
00204 {
00205    // Add object to B-tree.
00206 
00207    if (IsArgNull("Add", obj)) return;
00208    if (!obj->IsSortable()) {
00209       Error("Add", "object must be sortable");
00210       return;
00211    }
00212    if (!fRoot) {
00213       fRoot = new TBtLeafNode(0, obj, this);
00214       R__CHECK(fRoot != 0);
00215       IncrNofKeys();
00216    } else {
00217       TBtNode *loc;
00218       Int_t idx;
00219       if (fRoot->Found(obj, &loc, &idx) != 0) {
00220          // loc and idx are set to either where the object
00221          // was found, or where it should go in the Btree.
00222          // Nothing is here now, but later we might give the user
00223          // the ability to declare a B-tree as `unique elements only',
00224          // in which case we would handle an exception here.
00225       }
00226       loc->Add(obj, idx);
00227    }
00228 }
00229 
00230 //______________________________________________________________________________
00231 TObject *TBtree::After(const TObject *) const
00232 {
00233    // Cannot use this method since B-tree decides order.
00234 
00235    MayNotUse("After");
00236    return 0;
00237 }
00238 
00239 //______________________________________________________________________________
00240 TObject *TBtree::Before(const TObject *) const
00241 {
00242    // May not use this method since B-tree decides order.
00243 
00244    MayNotUse("Before");
00245    return 0;
00246 }
00247 
00248 //______________________________________________________________________________
00249 void TBtree::Clear(Option_t *)
00250 {
00251    // Remove all objects from B-tree. Does NOT delete objects unless the TBtree
00252    // is the owner (set via SetOwner()).
00253 
00254    if (IsOwner())
00255       Delete();
00256    else {
00257       SafeDelete(fRoot);
00258       fSize = 0;
00259    }
00260 }
00261 
00262 //______________________________________________________________________________
00263 void TBtree::Delete(Option_t *)
00264 {
00265    // Remove all objects from B-tree AND delete all heap based objects.
00266 
00267    for (Int_t i = 0; i < fSize; i++) {
00268       TObject *obj = At(i);
00269       if (obj && obj->IsOnHeap())
00270          TCollection::GarbageCollect(obj);
00271    }
00272    SafeDelete(fRoot);
00273    fSize = 0;
00274 }
00275 
00276 //______________________________________________________________________________
00277 TObject *TBtree::FindObject(const char *name) const
00278 {
00279    // Find object using its name (see object's GetName()). Requires sequential
00280    // search of complete tree till object is found.
00281 
00282    return TCollection::FindObject(name);
00283 }
00284 
00285 //______________________________________________________________________________
00286 TObject *TBtree::FindObject(const TObject *obj) const
00287 {
00288    // Find object using the objects Compare() member function.
00289 
00290    if (!obj->IsSortable()) {
00291       Error("FindObject", "object must be sortable");
00292       return 0;
00293    }
00294    if (!fRoot)
00295       return 0;
00296    else {
00297       TBtNode *loc;
00298       Int_t idx;
00299       return fRoot->Found(obj, &loc, &idx);
00300    }
00301 }
00302 
00303 //______________________________________________________________________________
00304 Int_t TBtree::IdxAdd(const TObject &obj)
00305 {
00306    // Add object and return its index in the tree.
00307 
00308    Int_t r;
00309    if (!obj.IsSortable()) {
00310       Error("IdxAdd", "object must be sortable");
00311       return -1;
00312    }
00313    if (!fRoot) {
00314       fRoot = new TBtLeafNode(0, &obj, this);
00315       R__ASSERT(fRoot != 0);
00316       IncrNofKeys();
00317       r = 0;
00318    } else {
00319       TBtNode *loc;
00320       int idx;
00321       if (fRoot->Found(&obj, &loc, &idx) != 0) {
00322          // loc and idx are set to either where the object
00323          // was found, or where it should go in the Btree.
00324          // Nothing is here now, but later we might give the user
00325          // the ability to declare a B-tree as `unique elements only',
00326          // in which case we would handle an exception here.
00327          // cerr << "Multiple entry warning\n";
00328       } else {
00329          R__CHECK(loc->fIsLeaf);
00330       }
00331       if (loc->fIsLeaf) {
00332          if (loc->fParent == 0)
00333             r = idx;
00334          else
00335             r = idx + loc->fParent->FindRankUp(loc);
00336       } else {
00337          TBtInnerNode *iloc = (TBtInnerNode*) loc;
00338          r = iloc->FindRankUp(iloc->GetTree(idx));
00339       }
00340       loc->Add(&obj, idx);
00341    }
00342    R__CHECK(r == Rank(&obj) || &obj == (*this)[r]);
00343    return r;
00344 }
00345 
00346 //______________________________________________________________________________
00347 void TBtree::Init(Int_t order)
00348 {
00349    // Initialize a B-tree.
00350 
00351    if (order < 3) {
00352       Warning("Init", "order must be at least 3");
00353       order = 3;
00354    }
00355    fRoot   = 0;
00356    fOrder  = order;
00357    fOrder2 = 2 * (fOrder+1);
00358    fLeafMaxIndex  = fOrder2 - 1;     // fItem[0..fOrder2-1]
00359    fInnerMaxIndex = fOrder;          // fItem[1..fOrder]
00360    //
00361    // the low water marks trigger an exploration for balancing
00362    // or merging nodes.
00363    // When the size of a node falls below X, then it must be possible to
00364    // either balance this node with another node, or it must be possible
00365    // to merge this node with another node.
00366    // This can be guaranteed only if (this->Size() < (MaxSize()-1)/2).
00367    //
00368    //
00369 
00370    // == MaxSize() satisfies the above because we compare
00371    // lowwatermark with fLast
00372    fLeafLowWaterMark  = ((fLeafMaxIndex+1)-1) / 2 - 1;
00373    fInnerLowWaterMark = (fOrder-1) / 2;
00374 }
00375 
00376 //______________________________________________________________________________
00377 //void TBtree::PrintOn(ostream& out) const
00378 //{
00379 //   // Print a B-tree.
00380 //
00381 //   if (!fRoot)
00382 //      out << "<empty>";
00383 //   else
00384 //      fRoot->PrintOn(out);
00385 //}
00386 
00387 //______________________________________________________________________________
00388 TIterator *TBtree::MakeIterator(Bool_t dir) const
00389 {
00390    // Returns a B-tree iterator.
00391 
00392    return new TBtreeIter(this, dir);
00393 }
00394 
00395 //______________________________________________________________________________
00396 Int_t TBtree::Rank(const TObject *obj) const
00397 {
00398    // Returns the rank of the object in the tree.
00399 
00400    if (!obj->IsSortable()) {
00401       Error("Rank", "object must be sortable");
00402       return -1;
00403    }
00404    if (!fRoot)
00405       return -1;
00406    else
00407       return fRoot->FindRank(obj);
00408 }
00409 
00410 //______________________________________________________________________________
00411 TObject *TBtree::Remove(TObject *obj)
00412 {
00413    // Remove an object from the tree.
00414 
00415    if (!obj->IsSortable()) {
00416       Error("Remove", "object must be sortable");
00417       return 0;
00418    }
00419    if (!fRoot)
00420       return 0;
00421 
00422    TBtNode *loc;
00423    Int_t idx;
00424    TObject *ob = fRoot->Found(obj, &loc, &idx);
00425    if (!ob)
00426       return 0;
00427    loc->Remove(idx);
00428    return ob;
00429 }
00430 
00431 //______________________________________________________________________________
00432 void TBtree::RootIsFull()
00433 {
00434    // The root of the tree is full. Create an InnerNode that
00435    // points to it, and then inform the InnerNode that it is full.
00436 
00437    TBtNode *oldroot = fRoot;
00438    fRoot = new TBtInnerNode(0, this, oldroot);
00439    R__ASSERT(fRoot != 0);
00440    oldroot->Split();
00441 }
00442 
00443 //______________________________________________________________________________
00444 void TBtree::RootIsEmpty()
00445 {
00446    // If root is empty clean up its space.
00447 
00448    if (fRoot->fIsLeaf) {
00449       TBtLeafNode *lroot = (TBtLeafNode*)fRoot;
00450       R__CHECK(lroot->Psize() == 0);
00451       delete lroot;
00452       fRoot = 0;
00453    } else {
00454       TBtInnerNode *iroot = (TBtInnerNode*)fRoot;
00455       R__CHECK(iroot->Psize() == 0);
00456       fRoot = iroot->GetTree(0);
00457       fRoot->fParent = 0;
00458       delete iroot;
00459    }
00460 }
00461 
00462 //_______________________________________________________________________
00463 void TBtree::Streamer(TBuffer &b)
00464 {
00465    // Stream all objects in the btree to or from the I/O buffer.
00466 
00467    UInt_t R__s, R__c;
00468    if (b.IsReading()) {
00469       b.ReadVersion(&R__s, &R__c);   //Version_t v = b.ReadVersion();
00470       b >> fOrder;
00471       b >> fOrder2;
00472       b >> fInnerLowWaterMark;
00473       b >> fLeafLowWaterMark;
00474       b >> fInnerMaxIndex;
00475       b >> fLeafMaxIndex;
00476       TSeqCollection::Streamer(b);
00477       b.CheckByteCount(R__s, R__c,TBtree::IsA());
00478    } else {
00479       R__c = b.WriteVersion(TBtree::IsA(), kTRUE);
00480       b << fOrder;
00481       b << fOrder2;
00482       b << fInnerLowWaterMark;
00483       b << fLeafLowWaterMark;
00484       b << fInnerMaxIndex;
00485       b << fLeafMaxIndex;
00486       TSeqCollection::Streamer(b);
00487       b.SetByteCount(R__c, kTRUE);
00488    }
00489 }
00490 
00491 
00492 //////////////////////////////////////////////////////////////////////////
00493 //                                                                      //
00494 // TBtItem                                                              //
00495 //                                                                      //
00496 // Item stored in inner nodes of a TBtree.                              //
00497 //                                                                      //
00498 //////////////////////////////////////////////////////////////////////////
00499 
00500 //______________________________________________________________________________
00501 TBtItem::TBtItem()
00502 {
00503    // Create an item to be stored in the tree. An item contains a counter
00504    // of the number of keys (i.e. objects) in the node. A pointer to the
00505    // node and a pointer to the object being stored.
00506 
00507    fNofKeysInTree = 0;
00508    fTree = 0;
00509    fKey  = 0;
00510 }
00511 
00512 //______________________________________________________________________________
00513 TBtItem::TBtItem(TBtNode *n, TObject *obj)
00514 {
00515    // Create an item to be stored in the tree. An item contains a counter
00516    // of the number of keys (i.e. objects) in the node. A pointer to the
00517    // node and a pointer to the object being stored.
00518 
00519    fNofKeysInTree = n->NofKeys()+1;
00520    fTree = n;
00521    fKey  = obj;
00522 }
00523 
00524 //______________________________________________________________________________
00525 TBtItem::TBtItem(TObject *obj, TBtNode *n)
00526 {
00527    // Create an item to be stored in the tree. An item contains a counter
00528    // of the number of keys (i.e. objects) in the node. A pointer to the
00529    // node and a pointer to the object being stored.
00530 
00531    fNofKeysInTree = n->NofKeys()+1;
00532    fTree = n;
00533    fKey  = obj;
00534 }
00535 
00536 //______________________________________________________________________________
00537 TBtItem::~TBtItem()
00538 {
00539    // Delete a tree item.
00540 }
00541 
00542 
00543 //////////////////////////////////////////////////////////////////////////
00544 //                                                                      //
00545 // TBtNode                                                              //
00546 //                                                                      //
00547 // Abstract base class (ABC) of a TBtree node.                          //
00548 //                                                                      //
00549 //////////////////////////////////////////////////////////////////////////
00550 
00551 //______________________________________________________________________________
00552 TBtNode::TBtNode(Int_t isleaf, TBtInnerNode *p, TBtree *t)
00553 {
00554    // Create a B-tree node.
00555 
00556    fLast   = -1;
00557    fIsLeaf = isleaf;
00558    fParent = p;
00559    if (p == 0) {
00560       R__CHECK(t != 0);
00561       fTree = t;
00562    } else
00563 #ifdef cxxbug
00564 //  BUG in the cxx compiler. cxx complains that it cannot access fTree
00565 //  from TBtInnerNode. To reproduce the cxx bug uncomment the following line
00566 //  and delete the line after.
00567 //    fTree = p->fTree;
00568       fTree = p->GetParentTree();
00569 #else
00570       fTree = p->fTree;
00571 #endif
00572 }
00573 
00574 //______________________________________________________________________________
00575 TBtNode::~TBtNode()
00576 {
00577    // Delete a B-tree node.
00578 }
00579 
00580 
00581 //////////////////////////////////////////////////////////////////////////
00582 //                                                                      //
00583 // TBtreeIter                                                           //
00584 //                                                                      //
00585 // Iterator of btree.                                                   //
00586 //                                                                      //
00587 //////////////////////////////////////////////////////////////////////////
00588 
00589 ClassImp(TBtreeIter)
00590 
00591 //______________________________________________________________________________
00592 TBtreeIter::TBtreeIter(const TBtree *t, Bool_t dir)
00593             : fTree(t), fCurCursor(0), fCursor(0), fDirection(dir)
00594 {
00595    // Create a B-tree iterator.
00596 
00597    Reset();
00598 }
00599 
00600 //______________________________________________________________________________
00601 TBtreeIter::TBtreeIter(const TBtreeIter &iter) : TIterator(iter)
00602 {
00603    // Copy ctor.
00604 
00605    fTree      = iter.fTree;
00606    fCursor    = iter.fCursor;
00607    fCurCursor = iter.fCurCursor;
00608    fDirection = iter.fDirection;
00609 }
00610 
00611 //______________________________________________________________________________
00612 TIterator &TBtreeIter::operator=(const TIterator &rhs)
00613 {
00614    // Overridden assignment operator.
00615 
00616    if (this != &rhs && rhs.IsA() == TBtreeIter::Class()) {
00617       const TBtreeIter &rhs1 = (const TBtreeIter &)rhs;
00618       fTree      = rhs1.fTree;
00619       fCursor    = rhs1.fCursor;
00620       fCurCursor = rhs1.fCurCursor;
00621       fDirection = rhs1.fDirection;
00622    }
00623    return *this;
00624 }
00625 
00626 //______________________________________________________________________________
00627 TBtreeIter &TBtreeIter::operator=(const TBtreeIter &rhs)
00628 {
00629    // Overloaded assignment operator.
00630 
00631    if (this != &rhs) {
00632       fTree      = rhs.fTree;
00633       fCursor    = rhs.fCursor;
00634       fCurCursor = rhs.fCurCursor;
00635       fDirection = rhs.fDirection;
00636    }
00637    return *this;
00638 }
00639 
00640 //______________________________________________________________________________
00641 void TBtreeIter::Reset()
00642 {
00643    // Reset the B-tree iterator.
00644 
00645    if (fDirection == kIterForward)
00646       fCursor = 0;
00647    else
00648       fCursor = fTree->GetSize() - 1;
00649 
00650    fCurCursor = fCursor;
00651 }
00652 
00653 //______________________________________________________________________________
00654 TObject *TBtreeIter::Next()
00655 {
00656    // Get next object from B-tree. Returns 0 when no more objects in tree.
00657 
00658    fCurCursor = fCursor;
00659    if (fDirection == kIterForward) {
00660       if (fCursor < fTree->GetSize())
00661          return (*fTree)[fCursor++];
00662    } else {
00663       if (fCursor >= 0)
00664          return (*fTree)[fCursor--];
00665    }
00666    return 0;
00667 }
00668 
00669 //______________________________________________________________________________
00670 bool TBtreeIter::operator!=(const TIterator &aIter) const
00671 {
00672    // This operator compares two TIterator objects.
00673 
00674    if (nullptr == (&aIter))
00675       return (fCurCursor < fTree->GetSize());
00676 
00677    if (aIter.IsA() == TBtreeIter::Class()) {
00678       const TBtreeIter &iter(dynamic_cast<const TBtreeIter &>(aIter));
00679       return (fCurCursor != iter.fCurCursor);
00680    }
00681    return false; // for base class we don't implement a comparison
00682 }
00683 
00684 //______________________________________________________________________________
00685 bool TBtreeIter::operator!=(const TBtreeIter &aIter) const
00686 {
00687    // This operator compares two TBtreeIter objects.
00688 
00689    if (nullptr == (&aIter))
00690       return (fCurCursor < fTree->GetSize());
00691    return (fCurCursor != aIter.fCurCursor);
00692 }
00693 
00694 //______________________________________________________________________________
00695 TObject* TBtreeIter::operator*() const
00696 {
00697    // Return current object or nullptr.
00698 
00699    return (((fCurCursor >= 0) && (fCurCursor < fTree->GetSize())) ?
00700            (*fTree)[fCurCursor] : nullptr);
00701 }
00702 
00703 
00704 //////////////////////////////////////////////////////////////////////////
00705 //                                                                      //
00706 // TBtInnerNode                                                         //
00707 //                                                                      //
00708 // Inner node of a TBtree.                                              //
00709 //                                                                      //
00710 //////////////////////////////////////////////////////////////////////////
00711 
00712 //______________________________________________________________________________
00713 TBtInnerNode::TBtInnerNode(TBtInnerNode *p, TBtree *t) : TBtNode(0,p,t)
00714 {
00715    // Create a B-tree innernode.
00716 
00717    const Int_t index = MaxIndex() + 1;
00718    fItem = new TBtItem[ index ];
00719    if (fItem == 0)
00720       ::Fatal("TBtInnerNode::TBtInnerNode", "no more memory");
00721 }
00722 
00723 //______________________________________________________________________________
00724 TBtInnerNode::TBtInnerNode(TBtInnerNode *parent, TBtree *tree, TBtNode *oldroot)
00725                 : TBtNode(0, parent, tree)
00726 {
00727    // Called only by TBtree to initialize the TBtInnerNode that is
00728    // about to become the root.
00729 
00730    fItem = new TBtItem[MaxIndex()+1];
00731    if (fItem == 0)
00732       ::Fatal("TBtInnerNode::TBtInnerNode", "no more memory");
00733    Append(0, oldroot);
00734 }
00735 
00736 //______________________________________________________________________________
00737 TBtInnerNode::~TBtInnerNode()
00738 {
00739    // Constructor.
00740 
00741    if (fLast > 0)
00742       delete fItem[0].fTree;
00743    for (Int_t i = 1; i <= fLast; i++)
00744       delete fItem[i].fTree;
00745 
00746    delete [] fItem;
00747 }
00748 
00749 //______________________________________________________________________________
00750 void TBtInnerNode::Add(const TObject *obj, Int_t index)
00751 {
00752    // This is called only from TBtree::Add().
00753 
00754    R__ASSERT(index >= 1 && obj->IsSortable());
00755    TBtLeafNode *ln = GetTree(index-1)->LastLeafNode();
00756    ln->Add(obj, ln->fLast+1);
00757 }
00758 
00759 //______________________________________________________________________________
00760 void TBtInnerNode::AddElt(TBtItem &itm, Int_t at)
00761 {
00762    // Add one element.
00763 
00764    R__ASSERT(0 <= at && at <= fLast+1);
00765    R__ASSERT(fLast < MaxIndex());
00766    for (Int_t i = fLast+1; i > at ; i--)
00767       GetItem(i) = GetItem(i-1);
00768    SetItem(at, itm);
00769    fLast++;
00770 }
00771 
00772 //______________________________________________________________________________
00773 void TBtInnerNode::AddElt(Int_t at, TObject *k, TBtNode *t)
00774 {
00775    // Add one element.
00776 
00777    TBtItem newitem(k, t);
00778    AddElt(newitem, at);
00779 }
00780 
00781 //______________________________________________________________________________
00782 void TBtInnerNode::Add(TBtItem &itm, Int_t at)
00783 {
00784    // Add one element.
00785 
00786    AddElt(itm, at);
00787    if (IsFull())
00788       InformParent();
00789 }
00790 
00791 //______________________________________________________________________________
00792 void TBtInnerNode::Add(Int_t at, TObject *k, TBtNode *t)
00793 {
00794    // Add one element.
00795 
00796    TBtItem newitem(k, t);
00797    Add(newitem, at);
00798 }
00799 
00800 //______________________________________________________________________________
00801 void TBtInnerNode::AppendFrom(TBtInnerNode *src, Int_t start, Int_t stop)
00802 {
00803    // This should never create a full node that is, it is not used
00804    // anywhere where THIS could possibly be near full.
00805 
00806    if (start > stop)
00807       return;
00808    R__ASSERT(0 <= start && start <= src->fLast);
00809    R__ASSERT(0 <= stop  && stop  <= src->fLast );
00810    R__ASSERT(fLast + stop - start + 1 < MaxIndex()); // full-node check
00811    for (Int_t i = start; i <= stop; i++)
00812       SetItem(++fLast, src->GetItem(i));
00813 }
00814 
00815 //______________________________________________________________________________
00816 void TBtInnerNode::Append(TObject *d, TBtNode *n)
00817 {
00818    // Never called from anywhere where it might fill up THIS.
00819 
00820    R__ASSERT(fLast < MaxIndex());
00821    if (d) R__ASSERT(d->IsSortable());
00822    SetItem(++fLast, d, n);
00823 }
00824 
00825 //______________________________________________________________________________
00826 void TBtInnerNode::Append(TBtItem &itm)
00827 {
00828    // Append itm to this tree.
00829 
00830    R__ASSERT(fLast < MaxIndex());
00831    SetItem(++fLast, itm);
00832 }
00833 
00834 //______________________________________________________________________________
00835 void TBtInnerNode::BalanceWithLeft(TBtInnerNode *leftsib, Int_t pidx)
00836 {
00837    // THIS has more than LEFTSIB. Move some item from THIS to LEFTSIB.
00838    // PIDX is the index of the parent item that will change when keys
00839    // are moved.
00840 
00841    R__ASSERT(Vsize() >= leftsib->Psize());
00842    R__ASSERT(fParent->GetTree(pidx) == this);
00843    Int_t newThisSize = (Vsize() + leftsib->Psize())/2;
00844    Int_t noFromThis = Psize() - newThisSize;
00845    PushLeft(noFromThis, leftsib, pidx);
00846 }
00847 
00848 //______________________________________________________________________________
00849 void TBtInnerNode::BalanceWithRight(TBtInnerNode *rightsib, Int_t pidx)
00850 {
00851    // THIS has more than RIGHTSIB. Move some items from THIS to RIGHTSIB.
00852    // PIDX is the index of the parent item that will change when keys
00853    // are moved.
00854 
00855    R__ASSERT(Psize() >= rightsib->Vsize());
00856    R__ASSERT(fParent->GetTree(pidx) == rightsib);
00857    Int_t newThisSize = (Psize() + rightsib->Vsize())/2;
00858    Int_t noFromThis = Psize() - newThisSize;
00859    PushRight(noFromThis, rightsib, pidx);
00860 }
00861 
00862 //______________________________________________________________________________
00863 void TBtInnerNode::BalanceWith(TBtInnerNode *rightsib, Int_t pindx)
00864 {
00865    // PINDX is the index of the parent item whose key will change when
00866    // keys are shifted from one InnerNode to the other.
00867 
00868    if (Psize() < rightsib->Vsize())
00869       rightsib->BalanceWithLeft(this, pindx);
00870    else
00871       BalanceWithRight(rightsib, pindx);
00872 }
00873 
00874 //______________________________________________________________________________
00875 void TBtInnerNode::DecrNofKeys(TBtNode *that)
00876 {
00877    // THAT is a child of THIS that has just shrunk by 1.
00878 
00879    Int_t i = IndexOf(that);
00880    fItem[i].fNofKeysInTree--;
00881    if (fParent != 0)
00882       fParent->DecrNofKeys(this);
00883    else
00884       fTree->DecrNofKeys();
00885 }
00886 
00887 //______________________________________________________________________________
00888 Int_t TBtInnerNode::FindRank(const TObject *what) const
00889 {
00890    // Recursively look for WHAT starting in the current node.
00891 
00892    if (((TObject *)what)->Compare(GetKey(1)) < 0)
00893       return GetTree(0)->FindRank(what);
00894    Int_t sum = GetNofKeys(0);
00895    for (Int_t i = 1; i < fLast; i++) {
00896       if (((TObject*)what)->Compare(GetKey(i)) == 0)
00897          return sum;
00898       sum++;
00899       if (((TObject *)what)->Compare(GetKey(i+1)) < 0)
00900          return sum + GetTree(i)->FindRank(what);
00901       sum += GetNofKeys(i);
00902    }
00903    if (((TObject*)what)->Compare(GetKey(fLast)) == 0)
00904       return sum;
00905    sum++;
00906    // *what > GetKey(fLast), so recurse on last fItem.fTree
00907    return sum + GetTree(fLast)->FindRank(what);
00908 }
00909 
00910 //______________________________________________________________________________
00911 Int_t TBtInnerNode::FindRankUp(const TBtNode *that) const
00912 {
00913    // FindRankUp is FindRank in reverse.
00914    // Whereas FindRank looks for the object and computes the rank
00915    // along the way while walking DOWN the tree, FindRankUp already
00916    // knows where the object is and has to walk UP the tree from the
00917    // object to compute the rank.
00918 
00919    Int_t l   = IndexOf(that);
00920    Int_t sum = 0;
00921    for (Int_t i = 0; i < l; i++)
00922       sum += GetNofKeys(i);
00923    return sum + l + (fParent == 0 ? 0 : fParent->FindRankUp(this));
00924 }
00925 
00926 //______________________________________________________________________________
00927 TBtLeafNode *TBtInnerNode::FirstLeafNode()
00928 {
00929    // Return the first leaf node.
00930 
00931    return GetTree(0)->FirstLeafNode();
00932 }
00933 
00934 //______________________________________________________________________________
00935 TObject *TBtInnerNode::Found(const TObject *what, TBtNode **which, Int_t *where)
00936 {
00937    // Recursively look for WHAT starting in the current node.
00938 
00939    R__ASSERT(what->IsSortable());
00940    for (Int_t i = 1 ; i <= fLast; i++) {
00941       if (GetKey(i)->Compare(what) == 0) {
00942          // then could go in either fItem[i].fTree or fItem[i-1].fTree
00943          // should go in one with the most room, but that's kinda
00944          // hard to calculate, so we'll stick it in fItem[i].fTree
00945          *which = this;
00946          *where = i;
00947          return GetKey(i);
00948       }
00949       if (GetKey(i)->Compare(what) > 0)
00950          return GetTree(i-1)->Found(what, which, where);
00951    }
00952    // *what > *(*this)[fLast].fKey, so recurse on last fItem.fTree
00953    return GetTree(fLast)->Found(what, which, where);
00954 }
00955 
00956 //______________________________________________________________________________
00957 void TBtInnerNode::IncrNofKeys(TBtNode *that)
00958 {
00959    // THAT is a child of THIS that has just grown by 1.
00960 
00961    Int_t i = IndexOf(that);
00962    fItem[i].fNofKeysInTree++;
00963    if (fParent != 0)
00964       fParent->IncrNofKeys(this);
00965    else
00966       fTree->IncrNofKeys();
00967 }
00968 
00969 //______________________________________________________________________________
00970 Int_t TBtInnerNode::IndexOf(const TBtNode *that) const
00971 {
00972    // Returns a number in the range 0 to this->fLast
00973    // 0 is returned if THAT == fTree[0].
00974 
00975    for (Int_t i = 0; i <= fLast; i++)
00976       if (GetTree(i) == that)
00977          return i;
00978    R__CHECK(0);
00979    return 0;
00980 }
00981 
00982 //______________________________________________________________________________
00983 void TBtInnerNode::InformParent()
00984 {
00985    // Tell the parent that we are full.
00986 
00987    if (fParent == 0) {
00988       // then this is the root of the tree and needs to be split
00989       // inform the btree.
00990       R__ASSERT(fTree->fRoot == this);
00991       fTree->RootIsFull();
00992    } else
00993       fParent->IsFull(this);
00994 }
00995 
00996 //______________________________________________________________________________
00997 void TBtInnerNode::IsFull(TBtNode *that)
00998 {
00999    // The child node THAT is full. We will either redistribute elements
01000    // or create a new node and then redistribute.
01001    // In an attempt to minimize the number of splits, we adopt the following
01002    // strategy:
01003    //  * redistribute if possible
01004    //  * if not possible, then split with a sibling
01005 
01006    if (that->fIsLeaf) {
01007       TBtLeafNode *leaf = (TBtLeafNode *)that;
01008       TBtLeafNode *left = 0;
01009       TBtLeafNode *right= 0;
01010       // split LEAF only if both sibling nodes are full.
01011       Int_t leafidx = IndexOf(leaf);
01012       Int_t hasRightSib = (leafidx < fLast) &&
01013                            ((right = (TBtLeafNode*)GetTree(leafidx+1)) != 0);
01014       Int_t hasLeftSib  = (leafidx > 0) &&
01015                            ((left = (TBtLeafNode*)GetTree(leafidx-1)) != 0);
01016       Int_t rightSibFull = (hasRightSib && right->IsAlmostFull());
01017       Int_t leftSibFull  = (hasLeftSib  && left->IsAlmostFull());
01018       if (rightSibFull) {
01019          if (leftSibFull) {
01020             // both full, so pick one to split with
01021             left->SplitWith(leaf, leafidx);
01022          } else if (hasLeftSib) {
01023             // left sib not full, so balance with it
01024             leaf->BalanceWithLeft(left, leafidx);
01025          } else {
01026             // there is no left sibling, so split with right
01027             leaf->SplitWith(right, leafidx+1);
01028          }
01029       } else if (hasRightSib) {
01030          // right sib not full, so balance with it
01031          leaf->BalanceWithRight(right, leafidx+1);
01032       } else if (leftSibFull) {
01033          // no right sib, and left sib is full, so split with it
01034          left->SplitWith(leaf, leafidx);
01035       } else if (hasLeftSib) {
01036          // left sib not full so balance with it
01037          leaf->BalanceWithLeft(left, leafidx);
01038       } else {
01039          // neither a left or right sib; should never happen
01040          R__CHECK(0);
01041       }
01042    } else {
01043       TBtInnerNode *inner = (TBtInnerNode *)that;
01044       // split INNER only if both sibling nodes are full
01045       Int_t inneridx = IndexOf(inner);
01046       TBtInnerNode *left = 0;
01047       TBtInnerNode *right= 0;
01048       Int_t hasRightSib = (inneridx < fLast) &&
01049                            ((right = (TBtInnerNode*)GetTree(inneridx+1)) != 0);
01050       Int_t hasLeftSib  = (inneridx > 0) &&
01051                            ((left=(TBtInnerNode*)GetTree(inneridx-1)) != 0);
01052       Int_t rightSibFull = (hasRightSib && right->IsAlmostFull());
01053       Int_t leftSibFull  = (hasLeftSib  && left->IsAlmostFull());
01054       if (rightSibFull) {
01055          if (leftSibFull) {
01056             left->SplitWith(inner, inneridx);
01057          } else if (hasLeftSib) {
01058             inner->BalanceWithLeft(left, inneridx);
01059          } else {
01060             // there is no left sibling
01061             inner->SplitWith(right, inneridx+1);
01062          }
01063       } else if (hasRightSib) {
01064          inner->BalanceWithRight(right, inneridx+1);
01065       } else if (leftSibFull) {
01066          left->SplitWith(inner, inneridx);
01067       } else if (hasLeftSib) {
01068          inner->BalanceWithLeft(left, inneridx);
01069       } else {
01070          R__CHECK(0);
01071       }
01072    }
01073 }
01074 
01075 //______________________________________________________________________________
01076 void TBtInnerNode::IsLow(TBtNode *that)
01077 {
01078    // The child node THAT is <= half full. We will either redistribute
01079    // elements between children, or THAT will be merged with another child.
01080    // In an attempt to minimize the number of mergers, we adopt the following
01081    // strategy:
01082    //  * redistribute if possible
01083    //  * if not possible, then merge with a sibling
01084 
01085    if (that->fIsLeaf) {
01086       TBtLeafNode *leaf = (TBtLeafNode *)that;
01087       TBtLeafNode *left = 0;
01088       TBtLeafNode *right= 0;
01089       // split LEAF only if both sibling nodes are full.
01090       Int_t leafidx = IndexOf(leaf);
01091       Int_t hasRightSib = (leafidx < fLast) &&
01092                            ((right = (TBtLeafNode*)GetTree(leafidx+1)) != 0);
01093       Int_t hasLeftSib  = (leafidx > 0) &&
01094                            ((left = (TBtLeafNode*)GetTree(leafidx-1)) != 0);
01095       if (hasRightSib && (leaf->Psize() + right->Vsize()) >= leaf->MaxPsize()) {
01096          // then cannot merge,
01097          // and balancing this and rightsib will leave them both
01098          // more than half full
01099          leaf->BalanceWith(right, leafidx+1);
01100       } else if (hasLeftSib && (leaf->Vsize() + left->Psize()) >= leaf->MaxPsize()) {
01101          // ditto
01102          left->BalanceWith(leaf, leafidx);
01103       } else if (hasLeftSib) {
01104          // then they should be merged
01105          left->MergeWithRight(leaf, leafidx);
01106       } else if (hasRightSib) {
01107          leaf->MergeWithRight(right, leafidx+1);
01108       } else {
01109          R__CHECK(0); // should never happen
01110       }
01111    } else {
01112       TBtInnerNode *inner = (TBtInnerNode *)that;
01113 
01114       Int_t inneridx = IndexOf(inner);
01115       TBtInnerNode *left = 0;
01116       TBtInnerNode *right= 0;
01117       Int_t hasRightSib = (inneridx < fLast) &&
01118                            ((right = (TBtInnerNode*)GetTree(inneridx+1)) != 0);
01119       Int_t hasLeftSib  = (inneridx > 0) &&
01120                            ((left = (TBtInnerNode*)GetTree(inneridx-1)) != 0);
01121       if (hasRightSib && (inner->Psize() + right->Vsize()) >= inner->MaxPsize()) {
01122          // cannot merge
01123          inner->BalanceWith(right, inneridx+1);
01124       } else if (hasLeftSib && (inner->Vsize() + left->Psize()) >= inner->MaxPsize()) {
01125          // cannot merge
01126          left->BalanceWith(inner, inneridx);
01127       } else if (hasLeftSib) {
01128          left->MergeWithRight(inner, inneridx);
01129       } else if (hasRightSib) {
01130          inner->MergeWithRight(right, inneridx+1);
01131       } else {
01132          R__CHECK(0);
01133       }
01134    }
01135 }
01136 
01137 //______________________________________________________________________________
01138 TBtLeafNode *TBtInnerNode::LastLeafNode()
01139 {
01140    // Return the last leaf node.
01141 
01142    return GetTree(fLast)->LastLeafNode();
01143 }
01144 
01145 //______________________________________________________________________________
01146 void TBtInnerNode::MergeWithRight(TBtInnerNode *rightsib, Int_t pidx)
01147 {
01148    // Merge the 2 part of the tree.
01149 
01150    R__ASSERT(Psize() + rightsib->Vsize() < MaxIndex());
01151    if (rightsib->Psize() > 0)
01152       rightsib->PushLeft(rightsib->Psize(), this, pidx);
01153    rightsib->SetKey(0, fParent->GetKey(pidx));
01154    AppendFrom(rightsib, 0, 0);
01155    fParent->IncNofKeys(pidx-1, rightsib->GetNofKeys(0)+1);
01156    fParent->RemoveItem(pidx);
01157    delete rightsib;
01158 }
01159 
01160 //______________________________________________________________________________
01161 Int_t TBtInnerNode::NofKeys() const
01162 {
01163    // Number of key.
01164 
01165    Int_t sum = 0;
01166    for (Int_t i = 0; i <= fLast; i++)
01167       sum += GetNofKeys(i);
01168    return sum + Psize();
01169 }
01170 
01171 //______________________________________________________________________________
01172 TObject *TBtInnerNode::operator[](Int_t idx) const
01173 {
01174    // return an element.
01175 
01176    for (Int_t j = 0; j <= fLast; j++) {
01177       Int_t r;
01178       if (idx < (r = GetNofKeys(j)))
01179          return (*GetTree(j))[idx];
01180       if (idx == r) {
01181          if (j == fLast) {
01182             ::Error("TBtInnerNode::operator[]", "should not happen, 0 returned");
01183             return 0;
01184          } else
01185             return GetKey(j+1);
01186       }
01187       idx -= r+1; // +1 because of the key in the node
01188    }
01189    ::Error("TBtInnerNode::operator[]", "should not happen, 0 returned");
01190    return 0;
01191 }
01192 
01193 //______________________________________________________________________________
01194 void TBtInnerNode::PushLeft(Int_t noFromThis, TBtInnerNode *leftsib, Int_t pidx)
01195 {
01196    // noFromThis==1 => moves the parent item into the leftsib,
01197    // and the first item in this's array into the parent item.
01198 
01199    R__ASSERT(fParent->GetTree(pidx) == this);
01200    R__ASSERT(noFromThis > 0 && noFromThis <= Psize());
01201    R__ASSERT(noFromThis + leftsib->Psize() < MaxPsize());
01202    SetKey(0, fParent->GetKey(pidx)); // makes AppendFrom's job easier
01203    leftsib->AppendFrom(this, 0, noFromThis-1);
01204    ShiftLeft(noFromThis);
01205    fParent->SetKey(pidx, GetKey(0));
01206    fParent->SetNofKeys(pidx-1, leftsib->NofKeys());
01207    fParent->SetNofKeys(pidx, NofKeys());
01208 }
01209 
01210 //______________________________________________________________________________
01211 void TBtInnerNode::PushRight(Int_t noFromThis, TBtInnerNode *rightsib, Int_t pidx)
01212 {
01213    // The operation is three steps:
01214    //  Step I.   Make room for the incoming keys in RIGHTSIB.
01215    //  Step II.  Move the items from THIS into RIGHTSIB.
01216    //  Step III. Update the length of THIS.
01217 
01218    R__ASSERT(noFromThis > 0 && noFromThis <= Psize());
01219    R__ASSERT(noFromThis + rightsib->Psize() < rightsib->MaxPsize());
01220    R__ASSERT(fParent->GetTree(pidx) == rightsib);
01221 
01222    //
01223    // Step I. Make space for noFromThis items
01224    //
01225    Int_t start = fLast - noFromThis + 1;
01226    Int_t tgt, src;
01227    tgt = rightsib->fLast + noFromThis;
01228    src = rightsib->fLast;
01229    rightsib->fLast = tgt;
01230    rightsib->SetKey(0, fParent->GetKey(pidx));
01231    IncNofKeys(0);
01232    while (src >= 0) {
01233       // do this kind of assignment on TBtInnerNode items only when
01234       // the parent fields of the moved items do not change, as they
01235       // don't here.
01236       // Otherwise, use SetItem so the parents are updated appropriately.
01237       rightsib->GetItem(tgt--) = rightsib->GetItem(src--);
01238    }
01239 
01240    // Step II. Move the items from THIS into RIGHTSIB
01241    for (Int_t i = fLast; i >= start; i-- ) {
01242       // this is the kind of assignment to use when parents change
01243       rightsib->SetItem(tgt--, GetItem(i));
01244    }
01245    fParent->SetKey(pidx, rightsib->GetKey(0));
01246    DecNofKeys(0);
01247    R__CHECK(tgt == -1);
01248 
01249    // Step III.
01250    fLast -= noFromThis;
01251 
01252    // Step VI.  update NofKeys
01253    fParent->SetNofKeys(pidx-1, NofKeys());
01254    fParent->SetNofKeys(pidx, rightsib->NofKeys());
01255 }
01256 
01257 //______________________________________________________________________________
01258 void TBtInnerNode::Remove(Int_t index)
01259 {
01260    // Remove an element.
01261 
01262    R__ASSERT(index >= 1 && index <= fLast);
01263    TBtLeafNode *lf = GetTree(index)->FirstLeafNode();
01264    SetKey(index, lf->fItem[0]);
01265    lf->RemoveItem(0);
01266 }
01267 
01268 //______________________________________________________________________________
01269 void TBtInnerNode::RemoveItem(Int_t index)
01270 {
01271    // Remove an item.
01272 
01273    R__ASSERT(index >= 1 && index <= fLast);
01274    for (Int_t to = index; to < fLast; to++)
01275       fItem[to] = fItem[to+1];
01276    fLast--;
01277    if (IsLow()) {
01278       if (fParent == 0) {
01279          // then this is the root; when only one child, make the child the root
01280          if (Psize() == 0)
01281             fTree->RootIsEmpty();
01282       } else
01283          fParent->IsLow(this);
01284    }
01285 }
01286 
01287 //______________________________________________________________________________
01288 void TBtInnerNode::ShiftLeft(Int_t cnt)
01289 {
01290    // Shift to the left.
01291 
01292    if (cnt <= 0)
01293       return;
01294    for (Int_t i = cnt; i <= fLast; i++)
01295       GetItem(i-cnt) = GetItem(i);
01296    fLast -= cnt;
01297 }
01298 
01299 //______________________________________________________________________________
01300 void TBtInnerNode::Split()
01301 {
01302    // This function is called only when THIS is the only descendent
01303    // of the root node, and THIS needs to be split.
01304    // Assumes that idx of THIS in fParent is 0.
01305 
01306    TBtInnerNode *newnode = new TBtInnerNode(fParent);
01307    R__CHECK(newnode != 0);
01308    fParent->Append(GetKey(fLast), newnode);
01309    newnode->AppendFrom(this, fLast, fLast);
01310    fLast--;
01311    fParent->IncNofKeys(1, newnode->GetNofKeys(0));
01312    fParent->DecNofKeys(0, newnode->GetNofKeys(0));
01313    BalanceWithRight(newnode, 1);
01314 }
01315 
01316 //______________________________________________________________________________
01317 void TBtInnerNode::SplitWith(TBtInnerNode *rightsib, Int_t keyidx)
01318 {
01319    // THIS and SIB are too full; create a NEWNODE, and balance
01320    // the number of keys between the three of them.
01321    //
01322    // picture: (also see Knuth Vol 3 pg 478)
01323    //               keyidx keyidx+1
01324    //            +--+--+--+--+--+--...
01325    //            |  |  |  |  |  |
01326    // fParent--->|  |     |     |
01327    //            |  |     |     |
01328    //            +*-+*-+*-+--+--+--...
01329    //             |  |  |
01330    //        +----+  |  +-----+
01331    //        |       +-----+  |
01332    //        V             |  V
01333    //        +----------+  |  +----------+
01334    //        |          |  |  |          |
01335    //  this->|          |  |  |          |<--sib
01336    //        +----------+  |  +----------+
01337    //                      V
01338    //                    data
01339    //
01340    // keyidx is the index of where the sibling is, and where the
01341    // newly created node will be recorded (sibling will be moved to
01342    // keyidx+1)
01343 
01344    R__ASSERT(keyidx > 0 && keyidx <= fParent->fLast);
01345 
01346    rightsib->SetKey(0, fParent->GetKey(keyidx));
01347    Int_t nofKeys      = Psize() + rightsib->Vsize();
01348    Int_t newSizeThis  = nofKeys / 3;
01349    Int_t newSizeNew   = (nofKeys - newSizeThis) / 2;
01350    Int_t newSizeSib   = (nofKeys - newSizeThis - newSizeNew);
01351    Int_t noFromThis   = Psize() - newSizeThis;
01352    Int_t noFromSib    = rightsib->Vsize() - newSizeSib;
01353    // because of their smaller size, this TBtInnerNode may not have to
01354    // give up any elements to the new node.  I.e., noFromThis == 0.
01355    // This will not happen for TBtLeafNodes.
01356    // We handle this by pulling an item from the rightsib.
01357    R__CHECK(noFromThis >= 0);
01358    R__CHECK(noFromSib >= 1);
01359    TBtInnerNode *newNode = new TBtInnerNode(fParent);
01360    R__CHECK(newNode != 0);
01361    if (noFromThis > 0) {
01362       newNode->Append(GetItem(fLast));
01363       fParent->AddElt(keyidx, GetKey(fLast--), newNode);
01364       if (noFromThis > 2)
01365          this->PushRight(noFromThis-1, newNode, keyidx);
01366       rightsib->PushLeft(noFromSib, newNode, keyidx+1);
01367    } else {
01368       // pull an element from the rightsib
01369       newNode->Append(rightsib->GetItem(0));
01370       fParent->AddElt(keyidx+1, rightsib->GetKey(1), rightsib);
01371       rightsib->ShiftLeft(1);
01372       fParent->SetTree(keyidx, newNode);
01373       rightsib->PushLeft(noFromSib-1, newNode, keyidx+1);
01374    }
01375    fParent->SetNofKeys(keyidx-1, this->NofKeys());
01376    fParent->SetNofKeys(keyidx, newNode->NofKeys());
01377    fParent->SetNofKeys(keyidx+1, rightsib->NofKeys());
01378    if (fParent->IsFull())
01379       fParent->InformParent();
01380 }
01381 
01382 
01383 //////////////////////////////////////////////////////////////////////////
01384 //                                                                      //
01385 // TBtLeafNode                                                          //
01386 //                                                                      //
01387 // Leaf node of a TBtree.                                               //
01388 //                                                                      //
01389 //////////////////////////////////////////////////////////////////////////
01390 
01391 //______________________________________________________________________________
01392 TBtLeafNode::TBtLeafNode(TBtInnerNode *p, const TObject *obj, TBtree *t): TBtNode(1, p, t)
01393 {
01394    // Constructor.
01395 
01396    fItem = new TObject *[MaxIndex()+1];
01397    memset(fItem, 0, (MaxIndex()+1)*sizeof(TObject*));
01398 
01399    R__ASSERT(fItem != 0);
01400    if (obj != 0)
01401       fItem[++fLast] = (TObject*)obj;   // cast const away
01402 }
01403 
01404 //______________________________________________________________________________
01405 TBtLeafNode::~TBtLeafNode()
01406 {
01407    // Destructor.
01408 
01409    delete [] fItem;
01410 }
01411 
01412 //______________________________________________________________________________
01413 void TBtLeafNode::Add(const TObject *obj, Int_t index)
01414 {
01415    // Add the object OBJ to the leaf node, inserting it at location INDEX
01416    // in the fItem array.
01417 
01418    R__ASSERT(obj->IsSortable());
01419    R__ASSERT(0 <= index && index <= fLast+1);
01420    R__ASSERT(fLast <= MaxIndex());
01421    for (Int_t i = fLast+1; i > index ; i--)
01422       fItem[i] = fItem[i-1];
01423    fItem[index] = (TObject *)obj;
01424    fLast++;
01425 
01426    // check for overflow
01427    if (fParent == 0)
01428       fTree->IncrNofKeys();
01429    else
01430       fParent->IncrNofKeys(this);
01431 
01432    if (IsFull()) {
01433       // it's full; tell parent node
01434       if (fParent == 0) {
01435          // this occurs when this leaf is the only node in the
01436          // btree, and this->fTree->fRoot == this
01437          R__CHECK(fTree->fRoot == this);
01438          // in which case we inform the btree, which can be
01439          // considered the parent of this node
01440          fTree->RootIsFull();
01441       } else {
01442          // the parent is responsible for splitting/balancing subnodes
01443          fParent->IsFull(this);
01444       }
01445    }
01446 }
01447 
01448 //______________________________________________________________________________
01449 void TBtLeafNode::AppendFrom(TBtLeafNode *src, Int_t start, Int_t stop)
01450 {
01451    // A convenience function, does not worry about the element in
01452    // the parent, simply moves elements from SRC[start] to SRC[stop]
01453    // into the current array.
01454    // This should never create a full node.
01455    // That is, it is not used anywhere where THIS could possibly be
01456    // near full.
01457    // Does NOT handle nofKeys.
01458 
01459    if (start > stop)
01460       return;
01461    R__ASSERT(0 <= start && start <= src->fLast);
01462    R__ASSERT(0 <= stop  && stop  <= src->fLast);
01463    R__ASSERT(fLast + stop - start + 1 < MaxIndex()); // full-node check
01464    for (Int_t i = start; i <= stop; i++)
01465       fItem[++fLast] = src->fItem[i];
01466    R__CHECK(fLast < MaxIndex());
01467 }
01468 
01469 //______________________________________________________________________________
01470 void TBtLeafNode::Append(TObject *obj)
01471 {
01472    // Never called from anywhere where it might fill up THIS
01473    // does NOT handle nofKeys.
01474 
01475    R__ASSERT(obj->IsSortable());
01476    fItem[++fLast] = obj;
01477    R__CHECK(fLast < MaxIndex());
01478 }
01479 
01480 //______________________________________________________________________________
01481 void TBtLeafNode::BalanceWithLeft(TBtLeafNode *leftsib, Int_t pidx)
01482 {
01483    // THIS has more than LEFTSIB;  move some items from THIS to LEFTSIB.
01484 
01485    R__ASSERT(Vsize() >= leftsib->Psize());
01486    Int_t newThisSize = (Vsize() + leftsib->Psize())/2;
01487    Int_t noFromThis  = Psize() - newThisSize;
01488    PushLeft(noFromThis, leftsib, pidx);
01489 }
01490 
01491 //______________________________________________________________________________
01492 void TBtLeafNode::BalanceWithRight(TBtLeafNode *rightsib, Int_t pidx)
01493 {
01494    // THIS has more than RIGHTSIB;  move some items from THIS to RIGHTSIB.
01495 
01496    R__ASSERT(Psize() >= rightsib->Vsize());
01497    Int_t newThisSize = (Psize() + rightsib->Vsize())/2;
01498    Int_t noFromThis  = Psize() - newThisSize;
01499    PushRight(noFromThis, rightsib, pidx);
01500 }
01501 
01502 //______________________________________________________________________________
01503 void TBtLeafNode::BalanceWith(TBtLeafNode *rightsib, Int_t pidx)
01504 {
01505    // PITEM is the parent item whose key will change when keys are shifted
01506    // from one LeafNode to the other.
01507 
01508    if (Psize() < rightsib->Vsize())
01509       rightsib->BalanceWithLeft(this, pidx);
01510    else
01511       BalanceWithRight(rightsib, pidx);
01512 }
01513 
01514 //______________________________________________________________________________
01515 Int_t TBtLeafNode::FindRank(const TObject *what) const
01516 {
01517    // WHAT was not in any inner node; it is either here, or it's
01518    // not in the tree.
01519 
01520    for (Int_t i = 0; i <= fLast; i++) {
01521       if (fItem[i]->Compare(what) == 0)
01522          return i;
01523       if (fItem[i]->Compare(what) > 0)
01524          return -1;
01525    }
01526    return -1;
01527 }
01528 
01529 //______________________________________________________________________________
01530 TBtLeafNode *TBtLeafNode::FirstLeafNode()
01531 {
01532    // Return the first node.
01533 
01534    return this;
01535 }
01536 
01537 //______________________________________________________________________________
01538 TObject *TBtLeafNode::Found(const TObject *what, TBtNode **which, Int_t *where)
01539 {
01540    // WHAT was not in any inner node; it is either here, or it's
01541    // not in the tree.
01542 
01543    R__ASSERT(what->IsSortable());
01544    for (Int_t i = 0; i <= fLast; i++) {
01545       if (fItem[i]->Compare(what) == 0) {
01546          *which = this;
01547          *where = i;
01548          return fItem[i];
01549       }
01550       if (fItem[i]->Compare(what) > 0) {
01551          *which = this;
01552          *where = i;
01553          return 0;
01554       }
01555    }
01556    *which = this;
01557    *where = fLast+1;
01558    return 0;
01559 }
01560 
01561 //______________________________________________________________________________
01562 Int_t TBtLeafNode::IndexOf(const TObject *that) const
01563 {
01564    // Returns a number in the range 0 to MaxIndex().
01565 
01566    for (Int_t i = 0; i <= fLast; i++) {
01567       if (fItem[i] == that)
01568          return i;
01569    }
01570    R__CHECK(0);
01571    return -1;
01572 }
01573 
01574 //______________________________________________________________________________
01575 TBtLeafNode *TBtLeafNode::LastLeafNode()
01576 {
01577    // return the last node.
01578    return this;
01579 }
01580 
01581 //______________________________________________________________________________
01582 void TBtLeafNode::MergeWithRight(TBtLeafNode *rightsib, Int_t pidx)
01583 {
01584    // Merge.
01585 
01586    R__ASSERT(Psize() + rightsib->Vsize() < MaxPsize());
01587    rightsib->PushLeft(rightsib->Psize(), this, pidx);
01588    Append(fParent->GetKey(pidx));
01589    fParent->SetNofKeys(pidx-1, NofKeys());
01590    fParent->RemoveItem(pidx);
01591    delete rightsib;
01592 }
01593 
01594 //______________________________________________________________________________
01595 Int_t TBtLeafNode::NofKeys(Int_t ) const
01596 {
01597    // Return the number of keys.
01598    return 1;
01599 }
01600 
01601 //______________________________________________________________________________
01602 Int_t TBtLeafNode::NofKeys() const
01603 {
01604    // Return the number of keys.
01605    return Psize();
01606 }
01607 
01608 //______________________________________________________________________________
01609 //void TBtLeafNode::PrintOn(ostream& out) const
01610 //{
01611 //    out << " < ";
01612 //    for (Int_t i = 0; i <= fLast; i++)
01613 //        out << *fItem[i] << " " ;
01614 //    out << "> ";
01615 //}
01616 
01617 //______________________________________________________________________________
01618 void TBtLeafNode::PushLeft(Int_t noFromThis, TBtLeafNode *leftsib, Int_t pidx)
01619 {
01620    // noFromThis==1 => moves the parent item into the leftsib,
01621    // and the first item in this's array into the parent item.
01622 
01623    R__ASSERT(noFromThis > 0 && noFromThis <= Psize());
01624    R__ASSERT(noFromThis + leftsib->Psize() < MaxPsize());
01625    R__ASSERT(fParent->GetTree(pidx) == this);
01626    leftsib->Append(fParent->GetKey(pidx));
01627    if (noFromThis > 1)
01628       leftsib->AppendFrom(this, 0, noFromThis-2);
01629    fParent->SetKey(pidx, fItem[noFromThis-1]);
01630    ShiftLeft(noFromThis);
01631    fParent->SetNofKeys(pidx-1, leftsib->NofKeys());
01632    fParent->SetNofKeys(pidx, NofKeys());
01633 }
01634 
01635 //______________________________________________________________________________
01636 void TBtLeafNode::PushRight(Int_t noFromThis, TBtLeafNode *rightsib, Int_t pidx)
01637 {
01638    // noFromThis==1 => moves the parent item into the
01639    // rightsib, and the last item in this's array into the parent
01640    // item.
01641 
01642    R__ASSERT(noFromThis > 0 && noFromThis <= Psize());
01643    R__ASSERT(noFromThis + rightsib->Psize() < MaxPsize());
01644    R__ASSERT(fParent->GetTree(pidx) == rightsib);
01645    // The operation is five steps:
01646    //  Step I.   Make room for the incoming keys in RIGHTSIB.
01647    //  Step II.  Move the key in the parent into RIGHTSIB.
01648    //  Step III. Move the items from THIS into RIGHTSIB.
01649    //  Step IV.  Move the item from THIS into the parent.
01650    //  Step V.   Update the length of THIS.
01651    //
01652    // Step I.: make space for noFromThis items
01653    //
01654    Int_t start = fLast - noFromThis + 1;
01655    Int_t tgt, src;
01656    tgt = rightsib->fLast + noFromThis;
01657    src = rightsib->fLast;
01658    rightsib->fLast = tgt;
01659    while (src >= 0)
01660       rightsib->fItem[tgt--] = rightsib->fItem[src--];
01661 
01662    // Step II. Move the key from the parent into place
01663    rightsib->fItem[tgt--] = fParent->GetKey(pidx);
01664 
01665    // Step III.Move the items from THIS into RIGHTSIB
01666    for (Int_t i = fLast; i > start; i--)
01667       rightsib->fItem[tgt--] = fItem[i];
01668    R__CHECK(tgt == -1);
01669 
01670    // Step IV.
01671    fParent->SetKey(pidx, fItem[start]);
01672 
01673    // Step V.
01674    fLast -= noFromThis;
01675 
01676    // Step VI.  update nofKeys
01677    fParent->SetNofKeys(pidx-1, NofKeys());
01678    fParent->SetNofKeys(pidx, rightsib->NofKeys());
01679 }
01680 
01681 //______________________________________________________________________________
01682 void TBtLeafNode::Remove(Int_t index)
01683 {
01684    // Remove an element.
01685 
01686    R__ASSERT(index >= 0 && index <= fLast);
01687    for (Int_t to = index; to < fLast; to++)
01688       fItem[to] = fItem[to+1];
01689    fLast--;
01690    if (fParent == 0)
01691       fTree->DecrNofKeys();
01692    else
01693       fParent->DecrNofKeys(this);
01694    if (IsLow()) {
01695       if (fParent == 0) {
01696          // then this is the root; when no keys left, inform the tree
01697          if (Psize() == 0)
01698             fTree->RootIsEmpty();
01699       } else
01700          fParent->IsLow(this);
01701    }
01702 }
01703 
01704 //______________________________________________________________________________
01705 void TBtLeafNode::ShiftLeft(Int_t cnt)
01706 {
01707    // Shift.
01708 
01709    if (cnt <= 0)
01710       return;
01711    for (Int_t i = cnt; i <= fLast; i++)
01712       fItem[i-cnt] = fItem[i];
01713    fLast -= cnt;
01714 }
01715 
01716 //______________________________________________________________________________
01717 void TBtLeafNode::Split()
01718 {
01719    // This function is called only when THIS is the only descendent
01720    // of the root node, and THIS needs to be split.
01721    // Assumes that idx of THIS in Parent is 0.
01722 
01723    TBtLeafNode *newnode = new TBtLeafNode(fParent);
01724    R__ASSERT(newnode != 0);
01725    fParent->Append(fItem[fLast--], newnode);
01726    fParent->SetNofKeys(0, fParent->GetTree(0)->NofKeys());
01727    fParent->SetNofKeys(1, fParent->GetTree(1)->NofKeys());
01728    BalanceWithRight(newnode, 1);
01729 }
01730 
01731 //______________________________________________________________________________
01732 void TBtLeafNode::SplitWith(TBtLeafNode *rightsib, Int_t keyidx)
01733 {
01734    // Split.
01735 
01736    R__ASSERT(fParent == rightsib->fParent);
01737    R__ASSERT(keyidx > 0 && keyidx <= fParent->fLast);
01738    Int_t nofKeys      = Psize() + rightsib->Vsize();
01739    Int_t newSizeThis  = nofKeys / 3;
01740    Int_t newSizeNew   = (nofKeys - newSizeThis) / 2;
01741    Int_t newSizeSib   = (nofKeys - newSizeThis - newSizeNew);
01742    Int_t noFromThis   = Psize() - newSizeThis;
01743    Int_t noFromSib    = rightsib->Vsize() - newSizeSib;
01744    R__CHECK(noFromThis >= 0);
01745    R__CHECK(noFromSib >= 1);
01746    TBtLeafNode *newNode  = new TBtLeafNode(fParent);
01747    R__ASSERT(newNode != 0);
01748    fParent->AddElt(keyidx, fItem[fLast--], newNode);
01749    fParent->SetNofKeys(keyidx, 0);
01750    fParent->DecNofKeys(keyidx-1);
01751    this->PushRight(noFromThis-1, newNode, keyidx);
01752    rightsib->PushLeft(noFromSib, newNode, keyidx+1);
01753    if (fParent->IsFull())
01754       fParent->InformParent();
01755 }

Generated on Tue Jul 5 14:11:37 2011 for ROOT_528-00b_version by  doxygen 1.5.1