ROOT  6.06/09
Reference Guide
TBtree.cxx
Go to the documentation of this file.
1 // @(#)root/cont:$Id$
2 // Author: Fons Rademakers 10/10/95
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /** \class TBtree
13 B-tree class. TBtree inherits from the TSeqCollection ABC.
14 
15 ## B-tree Implementation notes
16 
17 This implements B-trees with several refinements. Most of them can be found
18 in Knuth Vol 3, but some were developed to adapt to restrictions imposed
19 by C++. First, a restatement of Knuth's properties that a B-tree must
20 satisfy, assuming we make the enhancement he suggests in the paragraph
21 at the bottom of page 476. Instead of storing null pointers to non-existent
22 nodes (which Knuth calls the leaves) we utilize the space to store keys.
23 Therefore, what Knuth calls level (l-1) is the bottom of our tree, and
24 we call the nodes at this level LeafNodes. Other nodes are called InnerNodes.
25 The other enhancement we have adopted is in the paragraph at the bottom of
26 page 477: overflow control.
27 
28 The following are modifications of Knuth's properties on page 478:
29 
30  1. Every InnerNode has at most Order keys, and at most Order+1 sub-trees.
31  2. Every LeafNode has at most 2*(Order+1) keys.
32  3. An InnerNode with k keys has k+1 sub-trees.
33  4. Every InnerNode that is not the root has at least InnerLowWaterMark keys.
34  5. Every LeafNode that is not the root has at least LeafLowWaterMark keys.
35  6. If the root is a LeafNode, it has at least one key.
36  7. If the root is an InnerNode, it has at least one key and two sub-trees.
37  8. All LeafNodes are the same distance from the root as all the other
38  LeafNodes.
39  9. For InnerNode n with key n[i].key, then sub-tree n[i-1].tree contains
40  all keys < n[i].key, and sub-tree n[i].tree contains all keys
41  >= n[i].key.
42  10. Order is at least 3.
43 
44 The values of InnerLowWaterMark and LeafLowWaterMark may actually be set
45 by the user when the tree is initialized, but currently they are set
46 automatically to:
47 ~~~ {.cpp}
48  InnerLowWaterMark = ceiling(Order/2)
49  LeafLowWaterMark = Order - 1
50 ~~~
51 If the tree is only filled, then all the nodes will be at least 2/3 full.
52 They will almost all be exactly 2/3 full if the elements are added to the
53 tree in order (either increasing or decreasing). [Knuth says McCreight's
54 experiments showed almost 100% memory utilization. I don't see how that
55 can be given the algorithms that Knuth gives. McCreight must have used
56 a different scheme for balancing. [No, he used a different scheme for
57 splitting: he did a two-way split instead of the three way split as we do
58 here. Which means that McCreight does better on insertion of ordered data,
59 but we should do better on insertion of random data.]]
60 
61 It must also be noted that B-trees were designed for DISK access algorithms,
62 not necessarily in-memory sorting, as we intend it to be used here. However,
63 if the order is kept small (< 6?) any inefficiency is negligible for
64 in-memory sorting. Knuth points out that balanced trees are actually
65 preferable for memory sorting. I'm not sure that I believe this, but
66 it's interesting. Also, deleting elements from balanced binary trees, being
67 beyond the scope of Knuth's book (p. 465), is beyond my scope. B-trees
68 are good enough.
69 
70 A B-tree is declared to be of a certain ORDER (3 by default). This number
71 determines the number of keys contained in any interior node of the tree.
72 Each interior node will contain ORDER keys, and therefore ORDER+1 pointers
73 to sub-trees. The keys are numbered and indexed 1 to ORDER while the
74 pointers are numbered and indexed 0 to ORDER. The 0th ptr points to the
75 sub-tree of all elements that are less than key[1]. Ptr[1] points to the
76 sub-tree that contains all the elements greater than key[1] and less than
77 key[2]. etc. The array of pointers and keys is allocated as ORDER+1
78 pairs of keys and nodes, meaning that one key field (key[0]) is not used
79 and therefore wasted. Given that the number of interior nodes is
80 small, that this waste allows fewer cases of special code, and that it
81 is useful in certain of the methods, it was felt to be a worthwhile waste.
82 
83 The size of the exterior nodes (leaf nodes) does not need to be related to
84 the size of the interior nodes at all. Since leaf nodes contain only
85 keys, they may be as large or small as we like independent of the size
86 of the interior nodes. For no particular reason other than it seems like
87 a good idea, we will allocate 2*(ORDER+1) keys in each leaf node, and they
88 will be numbered and indexed from 0 to 2*ORDER+1. It does have the advantage
89 of keeping the size of the leaf and interior arrays the same, so that if we
90 find allocation and de-allocation of these arrays expensive, we can modify
91 their allocation to use a garbage ring, or something.
92 
93 Both of these numbers will be run-time constants associated with each tree
94 (each tree at run-time can be of a different order). The variable "order"
95 is the order of the tree, and the inclusive upper limit on the indices of
96 the keys in the interior nodes. The variable "order2" is the inclusive
97 upper limit on the indices of the leaf nodes, and is designed
98 ~~~ {.cpp}
99  (1) to keep the sizes of the two kinds of nodes the same;
100  (2) to keep the expressions involving the arrays of keys looking
101  somewhat the same: lower limit upper limit
102  for inner nodes: 1 order
103  for leaf nodes: 0 order2
104  Remember that index 0 of the inner nodes is special.
105 ~~~
106 Currently, order2 = 2*(order+1).
107 ~~~ {.cpp}
108  Picture: (also see Knuth Vol 3 pg 478)
109 
110  +--+--+--+--+--+--...
111  | | | | | |
112  parent--->| | | |
113  | | | |
114  +*-+*-+*-+--+--+--...
115  | | |
116  +----+ | +-----+
117  | +-----+ |
118  V | V
119  +----------+ | +----------+
120  | | | | |
121  this->| | | | |<--sib
122  +----------+ | +----------+
123  V
124  data
125 ~~~
126 It is conceptually VERY convenient to think of the data as being the
127 very first element of the sib node. Any primitive that tells sib to
128 perform some action on n nodes should include this 'hidden' element.
129 For InnerNodes, the hidden element has (physical) index 0 in the array,
130 and in LeafNodes, the hidden element has (virtual) index -1 in the array.
131 Therefore, there are two 'size' primitives for nodes:
132 ~~~ {.cpp}
133 Psize - the physical size: how many elements are contained in the
134  array in the node.
135 Vsize - the 'virtual' size; if the node is pointed to by
136  element 0 of the parent node, then Vsize == Psize;
137  otherwise the element in the parent item that points to this
138  node 'belongs' to this node, and Vsize == Psize+1;
139 ~~~
140 Parent nodes are always InnerNodes.
141 
142 These are the primitive operations on Nodes:
143 ~~~ {.cpp}
144 Append(elt) - adds an element to the end of the array of elements in a
145  node. It must never be called where appending the element
146  would fill the node.
147 Split() - divide a node in two, and create two new nodes.
148 SplitWith(sib) - create a third node between this node and the sib node,
149  divvying up the elements of their arrays.
150 PushLeft(n) - move n elements into the left sibling
151 PushRight(n) - move n elements into the right sibling
152 BalanceWithRight() - even up the number of elements in the two nodes.
153 BalanceWithLeft() - ditto
154 ~~~
155 To allow this implementation of btrees to also be an implementation of
156 sorted arrays/lists, the overhead is included to allow O(log n) access
157 of elements by their rank (`give me the 5th largest element').
158 Therefore, each Item keeps track of the number of keys in and below it
159 in the tree (remember, each item's tree is all keys to the RIGHT of the
160 item's own key).
161 ~~~ {.cpp}
162 [ [ < 0 1 2 3 > 4 < 5 6 7 > 8 < 9 10 11 12 > ] 13 [ < 14 15 16 > 17 < 18 19 20 > ] ]
163  4 1 1 1 1 4 1 1 1 5 1 1 1 1 7 3 1 1 1 4 1 1 1
164 ~~~
165 */
166 
167 #include <stdlib.h>
168 #include "TBtree.h"
169 
170 
172 
173 ////////////////////////////////////////////////////////////////////////////////
174 /// Create a B-tree of certain order (by default 3).
175 
176 TBtree::TBtree(int order)
177 {
178  Init(order);
179 }
180 
181 ////////////////////////////////////////////////////////////////////////////////
182 /// Delete B-tree. Objects are not deleted unless the TBtree is the
183 /// owner (set via SetOwner()).
184 
186 {
187  if (fRoot) {
188  Clear();
189  SafeDelete(fRoot);
190  }
191 }
192 
193 ////////////////////////////////////////////////////////////////////////////////
194 /// Add object to B-tree.
195 
197 {
198  if (IsArgNull("Add", obj)) return;
199  if (!obj->IsSortable()) {
200  Error("Add", "object must be sortable");
201  return;
202  }
203  if (!fRoot) {
204  fRoot = new TBtLeafNode(0, obj, this);
205  R__CHECK(fRoot != 0);
206  IncrNofKeys();
207  } else {
208  TBtNode *loc;
209  Int_t idx;
210  if (fRoot->Found(obj, &loc, &idx) != 0) {
211  // loc and idx are set to either where the object
212  // was found, or where it should go in the Btree.
213  // Nothing is here now, but later we might give the user
214  // the ability to declare a B-tree as `unique elements only',
215  // in which case we would handle an exception here.
216  }
217  loc->Add(obj, idx);
218  }
219 }
220 
221 ////////////////////////////////////////////////////////////////////////////////
222 /// Cannot use this method since B-tree decides order.
223 
225 {
226  MayNotUse("After");
227  return 0;
228 }
229 
230 ////////////////////////////////////////////////////////////////////////////////
231 /// May not use this method since B-tree decides order.
232 
234 {
235  MayNotUse("Before");
236  return 0;
237 }
238 
239 ////////////////////////////////////////////////////////////////////////////////
240 /// Remove all objects from B-tree. Does NOT delete objects unless the TBtree
241 /// is the owner (set via SetOwner()).
242 
244 {
245  if (IsOwner())
246  Delete();
247  else {
248  SafeDelete(fRoot);
249  fSize = 0;
250  }
251 }
252 
253 ////////////////////////////////////////////////////////////////////////////////
254 /// Remove all objects from B-tree AND delete all heap based objects.
255 
257 {
258  for (Int_t i = 0; i < fSize; i++) {
259  TObject *obj = At(i);
260  if (obj && obj->IsOnHeap())
262  }
263  SafeDelete(fRoot);
264  fSize = 0;
265 }
266 
267 ////////////////////////////////////////////////////////////////////////////////
268 /// Find object using its name (see object's GetName()). Requires sequential
269 /// search of complete tree till object is found.
270 
271 TObject *TBtree::FindObject(const char *name) const
272 {
273  return TCollection::FindObject(name);
274 }
275 
276 ////////////////////////////////////////////////////////////////////////////////
277 /// Find object using the objects Compare() member function.
278 
280 {
281  if (!obj->IsSortable()) {
282  Error("FindObject", "object must be sortable");
283  return 0;
284  }
285  if (!fRoot)
286  return 0;
287  else {
288  TBtNode *loc;
289  Int_t idx;
290  return fRoot->Found(obj, &loc, &idx);
291  }
292 }
293 
294 ////////////////////////////////////////////////////////////////////////////////
295 /// Add object and return its index in the tree.
296 
298 {
299  Int_t r;
300  if (!obj.IsSortable()) {
301  Error("IdxAdd", "object must be sortable");
302  return -1;
303  }
304  if (!fRoot) {
305  fRoot = new TBtLeafNode(0, &obj, this);
306  R__ASSERT(fRoot != 0);
307  IncrNofKeys();
308  r = 0;
309  } else {
310  TBtNode *loc;
311  int idx;
312  if (fRoot->Found(&obj, &loc, &idx) != 0) {
313  // loc and idx are set to either where the object
314  // was found, or where it should go in the Btree.
315  // Nothing is here now, but later we might give the user
316  // the ability to declare a B-tree as `unique elements only',
317  // in which case we would handle an exception here.
318  // std::cerr << "Multiple entry warning\n";
319  } else {
320  R__CHECK(loc->fIsLeaf);
321  }
322  if (loc->fIsLeaf) {
323  if (loc->fParent == 0)
324  r = idx;
325  else
326  r = idx + loc->fParent->FindRankUp(loc);
327  } else {
328  TBtInnerNode *iloc = (TBtInnerNode*) loc;
329  r = iloc->FindRankUp(iloc->GetTree(idx));
330  }
331  loc->Add(&obj, idx);
332  }
333  R__CHECK(r == Rank(&obj) || &obj == (*this)[r]);
334  return r;
335 }
336 
337 ////////////////////////////////////////////////////////////////////////////////
338 /// Initialize a B-tree.
339 
340 void TBtree::Init(Int_t order)
341 {
342  if (order < 3) {
343  Warning("Init", "order must be at least 3");
344  order = 3;
345  }
346  fRoot = 0;
347  fOrder = order;
348  fOrder2 = 2 * (fOrder+1);
349  fLeafMaxIndex = fOrder2 - 1; // fItem[0..fOrder2-1]
350  fInnerMaxIndex = fOrder; // fItem[1..fOrder]
351  //
352  // the low water marks trigger an exploration for balancing
353  // or merging nodes.
354  // When the size of a node falls below X, then it must be possible to
355  // either balance this node with another node, or it must be possible
356  // to merge this node with another node.
357  // This can be guaranteed only if (this->Size() < (MaxSize()-1)/2).
358  //
359  //
360 
361  // == MaxSize() satisfies the above because we compare
362  // lowwatermark with fLast
363  fLeafLowWaterMark = ((fLeafMaxIndex+1)-1) / 2 - 1;
364  fInnerLowWaterMark = (fOrder-1) / 2;
365 }
366 
367 //______________________________________________________________________________
368 //void TBtree::PrintOn(std::ostream& out) const
369 //{
370 // // Print a B-tree.
371 //
372 // if (!fRoot)
373 // out << "<empty>";
374 // else
375 // fRoot->PrintOn(out);
376 //}
377 
378 ////////////////////////////////////////////////////////////////////////////////
379 /// Returns a B-tree iterator.
380 
382 {
383  return new TBtreeIter(this, dir);
384 }
385 
386 ////////////////////////////////////////////////////////////////////////////////
387 /// Returns the rank of the object in the tree.
388 
390 {
391  if (!obj->IsSortable()) {
392  Error("Rank", "object must be sortable");
393  return -1;
394  }
395  if (!fRoot)
396  return -1;
397  else
398  return fRoot->FindRank(obj);
399 }
400 
401 ////////////////////////////////////////////////////////////////////////////////
402 /// Remove an object from the tree.
403 
405 {
406  if (!obj->IsSortable()) {
407  Error("Remove", "object must be sortable");
408  return 0;
409  }
410  if (!fRoot)
411  return 0;
412 
413  TBtNode *loc;
414  Int_t idx;
415  TObject *ob = fRoot->Found(obj, &loc, &idx);
416  if (!ob)
417  return 0;
418  loc->Remove(idx);
419  return ob;
420 }
421 
422 ////////////////////////////////////////////////////////////////////////////////
423 /// The root of the tree is full. Create an InnerNode that
424 /// points to it, and then inform the InnerNode that it is full.
425 
427 {
428  TBtNode *oldroot = fRoot;
429  fRoot = new TBtInnerNode(0, this, oldroot);
430  R__ASSERT(fRoot != 0);
431  oldroot->Split();
432 }
433 
434 ////////////////////////////////////////////////////////////////////////////////
435 /// If root is empty clean up its space.
436 
438 {
439  if (fRoot->fIsLeaf) {
440  TBtLeafNode *lroot = (TBtLeafNode*)fRoot;
441  R__CHECK(lroot->Psize() == 0);
442  delete lroot;
443  fRoot = 0;
444  } else {
445  TBtInnerNode *iroot = (TBtInnerNode*)fRoot;
446  R__CHECK(iroot->Psize() == 0);
447  fRoot = iroot->GetTree(0);
448  fRoot->fParent = 0;
449  delete iroot;
450  }
451 }
452 
453 ////////////////////////////////////////////////////////////////////////////////
454 /// Stream all objects in the btree to or from the I/O buffer.
455 
456 void TBtree::Streamer(TBuffer &b)
457 {
458  UInt_t R__s, R__c;
459  if (b.IsReading()) {
460  b.ReadVersion(&R__s, &R__c); //Version_t v = b.ReadVersion();
461  b >> fOrder;
462  b >> fOrder2;
463  b >> fInnerLowWaterMark;
464  b >> fLeafLowWaterMark;
465  b >> fInnerMaxIndex;
466  b >> fLeafMaxIndex;
467  TSeqCollection::Streamer(b);
468  b.CheckByteCount(R__s, R__c,TBtree::IsA());
469  } else {
470  R__c = b.WriteVersion(TBtree::IsA(), kTRUE);
471  b << fOrder;
472  b << fOrder2;
473  b << fInnerLowWaterMark;
474  b << fLeafLowWaterMark;
475  b << fInnerMaxIndex;
476  b << fLeafMaxIndex;
477  TSeqCollection::Streamer(b);
478  b.SetByteCount(R__c, kTRUE);
479  }
480 }
481 
482 
483 /** \class TBtItem
484 Item stored in inner nodes of a TBtree.
485 */
486 
487 ////////////////////////////////////////////////////////////////////////////////
488 /// Create an item to be stored in the tree. An item contains a counter
489 /// of the number of keys (i.e. objects) in the node. A pointer to the
490 /// node and a pointer to the object being stored.
491 
493 {
494  fNofKeysInTree = 0;
495  fTree = 0;
496  fKey = 0;
497 }
498 
499 ////////////////////////////////////////////////////////////////////////////////
500 /// Create an item to be stored in the tree. An item contains a counter
501 /// of the number of keys (i.e. objects) in the node. A pointer to the
502 /// node and a pointer to the object being stored.
503 
505 {
506  fNofKeysInTree = n->NofKeys()+1;
507  fTree = n;
508  fKey = obj;
509 }
510 
511 ////////////////////////////////////////////////////////////////////////////////
512 /// Create an item to be stored in the tree. An item contains a counter
513 /// of the number of keys (i.e. objects) in the node. A pointer to the
514 /// node and a pointer to the object being stored.
515 
517 {
518  fNofKeysInTree = n->NofKeys()+1;
519  fTree = n;
520  fKey = obj;
521 }
522 
523 ////////////////////////////////////////////////////////////////////////////////
524 /// Delete a tree item.
525 
527 {
528 }
529 
530 /** \class TBtNode
531 Abstract base class (ABC) of a TBtree node.
532 */
533 
534 ////////////////////////////////////////////////////////////////////////////////
535 /// Create a B-tree node.
536 
538 {
539  fLast = -1;
540  fIsLeaf = isleaf;
541  fParent = p;
542  if (p == 0) {
543  R__CHECK(t != 0);
544  fTree = t;
545  } else
546 #ifdef cxxbug
547 // BUG in the cxx compiler. cxx complains that it cannot access fTree
548 // from TBtInnerNode. To reproduce the cxx bug uncomment the following line
549 // and delete the line after.
550 // fTree = p->fTree;
551  fTree = p->GetParentTree();
552 #else
553  fTree = p->fTree;
554 #endif
555 }
556 
557 ////////////////////////////////////////////////////////////////////////////////
558 /// Delete a B-tree node.
559 
561 {
562 }
563 
564 /** \class TBtreeIter
565 // Iterator of btree.
566 */
567 
569 
570 ////////////////////////////////////////////////////////////////////////////////
571 /// Create a B-tree iterator.
572 
573 TBtreeIter::TBtreeIter(const TBtree *t, Bool_t dir)
574  : fTree(t), fCurCursor(0), fCursor(0), fDirection(dir)
575 {
576  Reset();
577 }
578 
579 ////////////////////////////////////////////////////////////////////////////////
580 /// Copy ctor.
581 
583 {
584  fTree = iter.fTree;
585  fCursor = iter.fCursor;
586  fCurCursor = iter.fCurCursor;
587  fDirection = iter.fDirection;
588 }
589 
590 ////////////////////////////////////////////////////////////////////////////////
591 /// Overridden assignment operator.
592 
594 {
595  if (this != &rhs && rhs.IsA() == TBtreeIter::Class()) {
596  const TBtreeIter &rhs1 = (const TBtreeIter &)rhs;
597  fTree = rhs1.fTree;
598  fCursor = rhs1.fCursor;
599  fCurCursor = rhs1.fCurCursor;
600  fDirection = rhs1.fDirection;
601  }
602  return *this;
603 }
604 
605 ////////////////////////////////////////////////////////////////////////////////
606 /// Overloaded assignment operator.
607 
609 {
610  if (this != &rhs) {
611  fTree = rhs.fTree;
612  fCursor = rhs.fCursor;
613  fCurCursor = rhs.fCurCursor;
614  fDirection = rhs.fDirection;
615  }
616  return *this;
617 }
618 
619 ////////////////////////////////////////////////////////////////////////////////
620 /// Reset the B-tree iterator.
621 
623 {
624  if (fDirection == kIterForward)
625  fCursor = 0;
626  else
627  fCursor = fTree->GetSize() - 1;
628 
630 }
631 
632 ////////////////////////////////////////////////////////////////////////////////
633 /// Get next object from B-tree. Returns 0 when no more objects in tree.
634 
636 {
638  if (fDirection == kIterForward) {
639  if (fCursor < fTree->GetSize())
640  return (*fTree)[fCursor++];
641  } else {
642  if (fCursor >= 0)
643  return (*fTree)[fCursor--];
644  }
645  return 0;
646 }
647 
648 ////////////////////////////////////////////////////////////////////////////////
649 /// This operator compares two TIterator objects.
650 
652 {
653  if (aIter.IsA() == TBtreeIter::Class()) {
654  const TBtreeIter &iter(dynamic_cast<const TBtreeIter &>(aIter));
655  return (fCurCursor != iter.fCurCursor);
656  }
657  return false; // for base class we don't implement a comparison
658 }
659 
660 ////////////////////////////////////////////////////////////////////////////////
661 /// This operator compares two TBtreeIter objects.
662 
664 {
665  return (fCurCursor != aIter.fCurCursor);
666 }
667 
668 ////////////////////////////////////////////////////////////////////////////////
669 /// Return current object or nullptr.
670 
672 {
673  return (((fCurCursor >= 0) && (fCurCursor < fTree->GetSize())) ?
674  (*fTree)[fCurCursor] : nullptr);
675 }
676 
677 /** \class TBtInnerNode
678 // Inner node of a TBtree.
679 */
680 
681 ////////////////////////////////////////////////////////////////////////////////
682 /// Create a B-tree innernode.
683 
685 {
686  const Int_t index = MaxIndex() + 1;
687  fItem = new TBtItem[ index ];
688  if (fItem == 0)
689  ::Fatal("TBtInnerNode::TBtInnerNode", "no more memory");
690 }
691 
692 ////////////////////////////////////////////////////////////////////////////////
693 /// Called only by TBtree to initialize the TBtInnerNode that is
694 /// about to become the root.
695 
697  : TBtNode(0, parent, tree)
698 {
699  fItem = new TBtItem[MaxIndex()+1];
700  if (fItem == 0)
701  ::Fatal("TBtInnerNode::TBtInnerNode", "no more memory");
702  Append(0, oldroot);
703 }
704 
705 ////////////////////////////////////////////////////////////////////////////////
706 /// Constructor.
707 
709 {
710  if (fLast > 0)
711  delete fItem[0].fTree;
712  for (Int_t i = 1; i <= fLast; i++)
713  delete fItem[i].fTree;
714 
715  delete [] fItem;
716 }
717 
718 ////////////////////////////////////////////////////////////////////////////////
719 /// This is called only from TBtree::Add().
720 
721 void TBtInnerNode::Add(const TObject *obj, Int_t index)
722 {
723  R__ASSERT(index >= 1 && obj->IsSortable());
724  TBtLeafNode *ln = GetTree(index-1)->LastLeafNode();
725  ln->Add(obj, ln->fLast+1);
726 }
727 
728 ////////////////////////////////////////////////////////////////////////////////
729 /// Add one element.
730 
732 {
733  R__ASSERT(0 <= at && at <= fLast+1);
734  R__ASSERT(fLast < MaxIndex());
735  for (Int_t i = fLast+1; i > at ; i--)
736  GetItem(i) = GetItem(i-1);
737  SetItem(at, itm);
738  fLast++;
739 }
740 
741 ////////////////////////////////////////////////////////////////////////////////
742 /// Add one element.
743 
745 {
746  TBtItem newitem(k, t);
747  AddElt(newitem, at);
748 }
749 
750 ////////////////////////////////////////////////////////////////////////////////
751 /// Add one element.
752 
754 {
755  AddElt(itm, at);
756  if (IsFull())
757  InformParent();
758 }
759 
760 ////////////////////////////////////////////////////////////////////////////////
761 /// Add one element.
762 
764 {
765  TBtItem newitem(k, t);
766  Add(newitem, at);
767 }
768 
769 ////////////////////////////////////////////////////////////////////////////////
770 /// This should never create a full node that is, it is not used
771 /// anywhere where THIS could possibly be near full.
772 
774 {
775  if (start > stop)
776  return;
777  R__ASSERT(0 <= start && start <= src->fLast);
778  R__ASSERT(0 <= stop && stop <= src->fLast );
779  R__ASSERT(fLast + stop - start + 1 < MaxIndex()); // full-node check
780  for (Int_t i = start; i <= stop; i++)
781  SetItem(++fLast, src->GetItem(i));
782 }
783 
784 ////////////////////////////////////////////////////////////////////////////////
785 /// Never called from anywhere where it might fill up THIS.
786 
788 {
789  R__ASSERT(fLast < MaxIndex());
790  if (d) R__ASSERT(d->IsSortable());
791  SetItem(++fLast, d, n);
792 }
793 
794 ////////////////////////////////////////////////////////////////////////////////
795 /// Append itm to this tree.
796 
798 {
799  R__ASSERT(fLast < MaxIndex());
800  SetItem(++fLast, itm);
801 }
802 
803 ////////////////////////////////////////////////////////////////////////////////
804 /// THIS has more than LEFTSIB. Move some item from THIS to LEFTSIB.
805 /// PIDX is the index of the parent item that will change when keys
806 /// are moved.
807 
809 {
810  R__ASSERT(Vsize() >= leftsib->Psize());
811  R__ASSERT(fParent->GetTree(pidx) == this);
812  Int_t newThisSize = (Vsize() + leftsib->Psize())/2;
813  Int_t noFromThis = Psize() - newThisSize;
814  PushLeft(noFromThis, leftsib, pidx);
815 }
816 
817 ////////////////////////////////////////////////////////////////////////////////
818 /// THIS has more than RIGHTSIB. Move some items from THIS to RIGHTSIB.
819 /// PIDX is the index of the parent item that will change when keys
820 /// are moved.
821 
823 {
824  R__ASSERT(Psize() >= rightsib->Vsize());
825  R__ASSERT(fParent->GetTree(pidx) == rightsib);
826  Int_t newThisSize = (Psize() + rightsib->Vsize())/2;
827  Int_t noFromThis = Psize() - newThisSize;
828  PushRight(noFromThis, rightsib, pidx);
829 }
830 
831 ////////////////////////////////////////////////////////////////////////////////
832 /// PINDX is the index of the parent item whose key will change when
833 /// keys are shifted from one InnerNode to the other.
834 
836 {
837  if (Psize() < rightsib->Vsize())
838  rightsib->BalanceWithLeft(this, pindx);
839  else
840  BalanceWithRight(rightsib, pindx);
841 }
842 
843 ////////////////////////////////////////////////////////////////////////////////
844 /// THAT is a child of THIS that has just shrunk by 1.
845 
847 {
848  Int_t i = IndexOf(that);
849  fItem[i].fNofKeysInTree--;
850  if (fParent != 0)
851  fParent->DecrNofKeys(this);
852  else
853  fTree->DecrNofKeys();
854 }
855 
856 ////////////////////////////////////////////////////////////////////////////////
857 /// Recursively look for WHAT starting in the current node.
858 
860 {
861  if (((TObject *)what)->Compare(GetKey(1)) < 0)
862  return GetTree(0)->FindRank(what);
863  Int_t sum = GetNofKeys(0);
864  for (Int_t i = 1; i < fLast; i++) {
865  if (((TObject*)what)->Compare(GetKey(i)) == 0)
866  return sum;
867  sum++;
868  if (((TObject *)what)->Compare(GetKey(i+1)) < 0)
869  return sum + GetTree(i)->FindRank(what);
870  sum += GetNofKeys(i);
871  }
872  if (((TObject*)what)->Compare(GetKey(fLast)) == 0)
873  return sum;
874  sum++;
875  // *what > GetKey(fLast), so recurse on last fItem.fTree
876  return sum + GetTree(fLast)->FindRank(what);
877 }
878 
879 ////////////////////////////////////////////////////////////////////////////////
880 /// FindRankUp is FindRank in reverse.
881 /// Whereas FindRank looks for the object and computes the rank
882 /// along the way while walking DOWN the tree, FindRankUp already
883 /// knows where the object is and has to walk UP the tree from the
884 /// object to compute the rank.
885 
887 {
888  Int_t l = IndexOf(that);
889  Int_t sum = 0;
890  for (Int_t i = 0; i < l; i++)
891  sum += GetNofKeys(i);
892  return sum + l + (fParent == 0 ? 0 : fParent->FindRankUp(this));
893 }
894 
895 ////////////////////////////////////////////////////////////////////////////////
896 /// Return the first leaf node.
897 
899 {
900  return GetTree(0)->FirstLeafNode();
901 }
902 
903 ////////////////////////////////////////////////////////////////////////////////
904 /// Recursively look for WHAT starting in the current node.
905 
907 {
908  R__ASSERT(what->IsSortable());
909  for (Int_t i = 1 ; i <= fLast; i++) {
910  if (GetKey(i)->Compare(what) == 0) {
911  // then could go in either fItem[i].fTree or fItem[i-1].fTree
912  // should go in one with the most room, but that's kinda
913  // hard to calculate, so we'll stick it in fItem[i].fTree
914  *which = this;
915  *where = i;
916  return GetKey(i);
917  }
918  if (GetKey(i)->Compare(what) > 0)
919  return GetTree(i-1)->Found(what, which, where);
920  }
921  // *what > *(*this)[fLast].fKey, so recurse on last fItem.fTree
922  return GetTree(fLast)->Found(what, which, where);
923 }
924 
925 ////////////////////////////////////////////////////////////////////////////////
926 /// THAT is a child of THIS that has just grown by 1.
927 
929 {
930  Int_t i = IndexOf(that);
931  fItem[i].fNofKeysInTree++;
932  if (fParent != 0)
933  fParent->IncrNofKeys(this);
934  else
935  fTree->IncrNofKeys();
936 }
937 
938 ////////////////////////////////////////////////////////////////////////////////
939 /// Returns a number in the range 0 to this->fLast
940 /// 0 is returned if THAT == fTree[0].
941 
943 {
944  for (Int_t i = 0; i <= fLast; i++)
945  if (GetTree(i) == that)
946  return i;
947  R__CHECK(0);
948  return 0;
949 }
950 
951 ////////////////////////////////////////////////////////////////////////////////
952 /// Tell the parent that we are full.
953 
955 {
956  if (fParent == 0) {
957  // then this is the root of the tree and needs to be split
958  // inform the btree.
959  R__ASSERT(fTree->fRoot == this);
960  fTree->RootIsFull();
961  } else
962  fParent->IsFull(this);
963 }
964 
965 ////////////////////////////////////////////////////////////////////////////////
966 /// The child node THAT is full. We will either redistribute elements
967 /// or create a new node and then redistribute.
968 /// In an attempt to minimize the number of splits, we adopt the following
969 /// strategy:
970 /// - redistribute if possible
971 /// - if not possible, then split with a sibling
972 
974 {
975  if (that->fIsLeaf) {
976  TBtLeafNode *leaf = (TBtLeafNode *)that;
977  TBtLeafNode *left = 0;
978  TBtLeafNode *right= 0;
979  // split LEAF only if both sibling nodes are full.
980  Int_t leafidx = IndexOf(leaf);
981  Int_t hasRightSib = (leafidx < fLast) &&
982  ((right = (TBtLeafNode*)GetTree(leafidx+1)) != 0);
983  Int_t hasLeftSib = (leafidx > 0) &&
984  ((left = (TBtLeafNode*)GetTree(leafidx-1)) != 0);
985  Int_t rightSibFull = (hasRightSib && right->IsAlmostFull());
986  Int_t leftSibFull = (hasLeftSib && left->IsAlmostFull());
987  if (rightSibFull) {
988  if (leftSibFull) {
989  // both full, so pick one to split with
990  left->SplitWith(leaf, leafidx);
991  } else if (hasLeftSib) {
992  // left sib not full, so balance with it
993  leaf->BalanceWithLeft(left, leafidx);
994  } else {
995  // there is no left sibling, so split with right
996  leaf->SplitWith(right, leafidx+1);
997  }
998  } else if (hasRightSib) {
999  // right sib not full, so balance with it
1000  leaf->BalanceWithRight(right, leafidx+1);
1001  } else if (leftSibFull) {
1002  // no right sib, and left sib is full, so split with it
1003  left->SplitWith(leaf, leafidx);
1004  } else if (hasLeftSib) {
1005  // left sib not full so balance with it
1006  leaf->BalanceWithLeft(left, leafidx);
1007  } else {
1008  // neither a left or right sib; should never happen
1009  R__CHECK(0);
1010  }
1011  } else {
1012  TBtInnerNode *inner = (TBtInnerNode *)that;
1013  // split INNER only if both sibling nodes are full
1014  Int_t inneridx = IndexOf(inner);
1015  TBtInnerNode *left = 0;
1016  TBtInnerNode *right= 0;
1017  Int_t hasRightSib = (inneridx < fLast) &&
1018  ((right = (TBtInnerNode*)GetTree(inneridx+1)) != 0);
1019  Int_t hasLeftSib = (inneridx > 0) &&
1020  ((left=(TBtInnerNode*)GetTree(inneridx-1)) != 0);
1021  Int_t rightSibFull = (hasRightSib && right->IsAlmostFull());
1022  Int_t leftSibFull = (hasLeftSib && left->IsAlmostFull());
1023  if (rightSibFull) {
1024  if (leftSibFull) {
1025  left->SplitWith(inner, inneridx);
1026  } else if (hasLeftSib) {
1027  inner->BalanceWithLeft(left, inneridx);
1028  } else {
1029  // there is no left sibling
1030  inner->SplitWith(right, inneridx+1);
1031  }
1032  } else if (hasRightSib) {
1033  inner->BalanceWithRight(right, inneridx+1);
1034  } else if (leftSibFull) {
1035  left->SplitWith(inner, inneridx);
1036  } else if (hasLeftSib) {
1037  inner->BalanceWithLeft(left, inneridx);
1038  } else {
1039  R__CHECK(0);
1040  }
1041  }
1042 }
1043 
1044 ////////////////////////////////////////////////////////////////////////////////
1045 /// The child node THAT is <= half full. We will either redistribute
1046 /// elements between children, or THAT will be merged with another child.
1047 /// In an attempt to minimize the number of mergers, we adopt the following
1048 /// strategy:
1049 /// - redistribute if possible
1050 /// - if not possible, then merge with a sibling
1051 
1053 {
1054  if (that->fIsLeaf) {
1055  TBtLeafNode *leaf = (TBtLeafNode *)that;
1056  TBtLeafNode *left = 0;
1057  TBtLeafNode *right= 0;
1058  // split LEAF only if both sibling nodes are full.
1059  Int_t leafidx = IndexOf(leaf);
1060  Int_t hasRightSib = (leafidx < fLast) &&
1061  ((right = (TBtLeafNode*)GetTree(leafidx+1)) != 0);
1062  Int_t hasLeftSib = (leafidx > 0) &&
1063  ((left = (TBtLeafNode*)GetTree(leafidx-1)) != 0);
1064  if (hasRightSib && (leaf->Psize() + right->Vsize()) >= leaf->MaxPsize()) {
1065  // then cannot merge,
1066  // and balancing this and rightsib will leave them both
1067  // more than half full
1068  leaf->BalanceWith(right, leafidx+1);
1069  } else if (hasLeftSib && (leaf->Vsize() + left->Psize()) >= leaf->MaxPsize()) {
1070  // ditto
1071  left->BalanceWith(leaf, leafidx);
1072  } else if (hasLeftSib) {
1073  // then they should be merged
1074  left->MergeWithRight(leaf, leafidx);
1075  } else if (hasRightSib) {
1076  leaf->MergeWithRight(right, leafidx+1);
1077  } else {
1078  R__CHECK(0); // should never happen
1079  }
1080  } else {
1081  TBtInnerNode *inner = (TBtInnerNode *)that;
1082 
1083  Int_t inneridx = IndexOf(inner);
1084  TBtInnerNode *left = 0;
1085  TBtInnerNode *right= 0;
1086  Int_t hasRightSib = (inneridx < fLast) &&
1087  ((right = (TBtInnerNode*)GetTree(inneridx+1)) != 0);
1088  Int_t hasLeftSib = (inneridx > 0) &&
1089  ((left = (TBtInnerNode*)GetTree(inneridx-1)) != 0);
1090  if (hasRightSib && (inner->Psize() + right->Vsize()) >= inner->MaxPsize()) {
1091  // cannot merge
1092  inner->BalanceWith(right, inneridx+1);
1093  } else if (hasLeftSib && (inner->Vsize() + left->Psize()) >= inner->MaxPsize()) {
1094  // cannot merge
1095  left->BalanceWith(inner, inneridx);
1096  } else if (hasLeftSib) {
1097  left->MergeWithRight(inner, inneridx);
1098  } else if (hasRightSib) {
1099  inner->MergeWithRight(right, inneridx+1);
1100  } else {
1101  R__CHECK(0);
1102  }
1103  }
1104 }
1105 
1106 ////////////////////////////////////////////////////////////////////////////////
1107 /// Return the last leaf node.
1108 
1110 {
1111  return GetTree(fLast)->LastLeafNode();
1112 }
1113 
1114 ////////////////////////////////////////////////////////////////////////////////
1115 /// Merge the 2 part of the tree.
1116 
1118 {
1119  R__ASSERT(Psize() + rightsib->Vsize() < MaxIndex());
1120  if (rightsib->Psize() > 0)
1121  rightsib->PushLeft(rightsib->Psize(), this, pidx);
1122  rightsib->SetKey(0, fParent->GetKey(pidx));
1123  AppendFrom(rightsib, 0, 0);
1124  fParent->IncNofKeys(pidx-1, rightsib->GetNofKeys(0)+1);
1125  fParent->RemoveItem(pidx);
1126  delete rightsib;
1127 }
1128 
1129 ////////////////////////////////////////////////////////////////////////////////
1130 /// Number of key.
1131 
1133 {
1134  Int_t sum = 0;
1135  for (Int_t i = 0; i <= fLast; i++)
1136  sum += GetNofKeys(i);
1137  return sum + Psize();
1138 }
1139 
1140 ////////////////////////////////////////////////////////////////////////////////
1141 /// return an element.
1142 
1144 {
1145  for (Int_t j = 0; j <= fLast; j++) {
1146  Int_t r;
1147  if (idx < (r = GetNofKeys(j)))
1148  return (*GetTree(j))[idx];
1149  if (idx == r) {
1150  if (j == fLast) {
1151  ::Error("TBtInnerNode::operator[]", "should not happen, 0 returned");
1152  return 0;
1153  } else
1154  return GetKey(j+1);
1155  }
1156  idx -= r+1; // +1 because of the key in the node
1157  }
1158  ::Error("TBtInnerNode::operator[]", "should not happen, 0 returned");
1159  return 0;
1160 }
1161 
1162 ////////////////////////////////////////////////////////////////////////////////
1163 /// noFromThis==1 => moves the parent item into the leftsib,
1164 /// and the first item in this's array into the parent item.
1165 
1166 void TBtInnerNode::PushLeft(Int_t noFromThis, TBtInnerNode *leftsib, Int_t pidx)
1167 {
1168  R__ASSERT(fParent->GetTree(pidx) == this);
1169  R__ASSERT(noFromThis > 0 && noFromThis <= Psize());
1170  R__ASSERT(noFromThis + leftsib->Psize() < MaxPsize());
1171  SetKey(0, fParent->GetKey(pidx)); // makes AppendFrom's job easier
1172  leftsib->AppendFrom(this, 0, noFromThis-1);
1173  ShiftLeft(noFromThis);
1174  fParent->SetKey(pidx, GetKey(0));
1175  fParent->SetNofKeys(pidx-1, leftsib->NofKeys());
1176  fParent->SetNofKeys(pidx, NofKeys());
1177 }
1178 
1179 ////////////////////////////////////////////////////////////////////////////////
1180 /// The operation is three steps:
1181 /// - Step I. Make room for the incoming keys in RIGHTSIB.
1182 /// - Step II. Move the items from THIS into RIGHTSIB.
1183 /// - Step III. Update the length of THIS.
1184 
1185 void TBtInnerNode::PushRight(Int_t noFromThis, TBtInnerNode *rightsib, Int_t pidx)
1186 {
1187  R__ASSERT(noFromThis > 0 && noFromThis <= Psize());
1188  R__ASSERT(noFromThis + rightsib->Psize() < rightsib->MaxPsize());
1189  R__ASSERT(fParent->GetTree(pidx) == rightsib);
1190 
1191  //
1192  // Step I. Make space for noFromThis items
1193  //
1194  Int_t start = fLast - noFromThis + 1;
1195  Int_t tgt, src;
1196  tgt = rightsib->fLast + noFromThis;
1197  src = rightsib->fLast;
1198  rightsib->fLast = tgt;
1199  rightsib->SetKey(0, fParent->GetKey(pidx));
1200  IncNofKeys(0);
1201  while (src >= 0) {
1202  // do this kind of assignment on TBtInnerNode items only when
1203  // the parent fields of the moved items do not change, as they
1204  // don't here.
1205  // Otherwise, use SetItem so the parents are updated appropriately.
1206  rightsib->GetItem(tgt--) = rightsib->GetItem(src--);
1207  }
1208 
1209  // Step II. Move the items from THIS into RIGHTSIB
1210  for (Int_t i = fLast; i >= start; i-- ) {
1211  // this is the kind of assignment to use when parents change
1212  rightsib->SetItem(tgt--, GetItem(i));
1213  }
1214  fParent->SetKey(pidx, rightsib->GetKey(0));
1215  DecNofKeys(0);
1216  R__CHECK(tgt == -1);
1217 
1218  // Step III.
1219  fLast -= noFromThis;
1220 
1221  // Step VI. update NofKeys
1222  fParent->SetNofKeys(pidx-1, NofKeys());
1223  fParent->SetNofKeys(pidx, rightsib->NofKeys());
1224 }
1225 
1226 ////////////////////////////////////////////////////////////////////////////////
1227 /// Remove an element.
1228 
1230 {
1231  R__ASSERT(index >= 1 && index <= fLast);
1232  TBtLeafNode *lf = GetTree(index)->FirstLeafNode();
1233  SetKey(index, lf->fItem[0]);
1234  lf->RemoveItem(0);
1235 }
1236 
1237 ////////////////////////////////////////////////////////////////////////////////
1238 /// Remove an item.
1239 
1241 {
1242  R__ASSERT(index >= 1 && index <= fLast);
1243  for (Int_t to = index; to < fLast; to++)
1244  fItem[to] = fItem[to+1];
1245  fLast--;
1246  if (IsLow()) {
1247  if (fParent == 0) {
1248  // then this is the root; when only one child, make the child the root
1249  if (Psize() == 0)
1250  fTree->RootIsEmpty();
1251  } else
1252  fParent->IsLow(this);
1253  }
1254 }
1255 
1256 ////////////////////////////////////////////////////////////////////////////////
1257 /// Shift to the left.
1258 
1260 {
1261  if (cnt <= 0)
1262  return;
1263  for (Int_t i = cnt; i <= fLast; i++)
1264  GetItem(i-cnt) = GetItem(i);
1265  fLast -= cnt;
1266 }
1267 
1268 ////////////////////////////////////////////////////////////////////////////////
1269 /// This function is called only when THIS is the only descendent
1270 /// of the root node, and THIS needs to be split.
1271 /// Assumes that idx of THIS in fParent is 0.
1272 
1274 {
1275  TBtInnerNode *newnode = new TBtInnerNode(fParent);
1276  R__CHECK(newnode != 0);
1277  fParent->Append(GetKey(fLast), newnode);
1278  newnode->AppendFrom(this, fLast, fLast);
1279  fLast--;
1280  fParent->IncNofKeys(1, newnode->GetNofKeys(0));
1281  fParent->DecNofKeys(0, newnode->GetNofKeys(0));
1282  BalanceWithRight(newnode, 1);
1283 }
1284 
1285 ////////////////////////////////////////////////////////////////////////////////
1286 /// THIS and SIB are too full; create a NEWNODE, and balance
1287 /// the number of keys between the three of them.
1288 ///
1289 /// picture: (also see Knuth Vol 3 pg 478)
1290 /// ~~~ {.cpp}
1291 /// keyidx keyidx+1
1292 /// +--+--+--+--+--+--...
1293 /// | | | | | |
1294 /// fParent--->| | | |
1295 /// | | | |
1296 /// +*-+*-+*-+--+--+--...
1297 /// | | |
1298 /// +----+ | +-----+
1299 /// | +-----+ |
1300 /// V | V
1301 /// +----------+ | +----------+
1302 /// | | | | |
1303 /// this->| | | | |<--sib
1304 /// +----------+ | +----------+
1305 /// V
1306 /// data
1307 /// ~~~
1308 /// keyidx is the index of where the sibling is, and where the
1309 /// newly created node will be recorded (sibling will be moved to
1310 /// keyidx+1)
1311 
1313 {
1314  R__ASSERT(keyidx > 0 && keyidx <= fParent->fLast);
1315 
1316  rightsib->SetKey(0, fParent->GetKey(keyidx));
1317  Int_t nofKeys = Psize() + rightsib->Vsize();
1318  Int_t newSizeThis = nofKeys / 3;
1319  Int_t newSizeNew = (nofKeys - newSizeThis) / 2;
1320  Int_t newSizeSib = (nofKeys - newSizeThis - newSizeNew);
1321  Int_t noFromThis = Psize() - newSizeThis;
1322  Int_t noFromSib = rightsib->Vsize() - newSizeSib;
1323  // because of their smaller size, this TBtInnerNode may not have to
1324  // give up any elements to the new node. I.e., noFromThis == 0.
1325  // This will not happen for TBtLeafNodes.
1326  // We handle this by pulling an item from the rightsib.
1327  R__CHECK(noFromThis >= 0);
1328  R__CHECK(noFromSib >= 1);
1329  TBtInnerNode *newNode = new TBtInnerNode(fParent);
1330  R__CHECK(newNode != 0);
1331  if (noFromThis > 0) {
1332  newNode->Append(GetItem(fLast));
1333  fParent->AddElt(keyidx, GetKey(fLast--), newNode);
1334  if (noFromThis > 2)
1335  this->PushRight(noFromThis-1, newNode, keyidx);
1336  rightsib->PushLeft(noFromSib, newNode, keyidx+1);
1337  } else {
1338  // pull an element from the rightsib
1339  newNode->Append(rightsib->GetItem(0));
1340  fParent->AddElt(keyidx+1, rightsib->GetKey(1), rightsib);
1341  rightsib->ShiftLeft(1);
1342  fParent->SetTree(keyidx, newNode);
1343  rightsib->PushLeft(noFromSib-1, newNode, keyidx+1);
1344  }
1345  fParent->SetNofKeys(keyidx-1, this->NofKeys());
1346  fParent->SetNofKeys(keyidx, newNode->NofKeys());
1347  fParent->SetNofKeys(keyidx+1, rightsib->NofKeys());
1348  if (fParent->IsFull())
1349  fParent->InformParent();
1350 }
1351 
1352 /** \class TBtLeafNode
1353 Leaf node of a TBtree.
1354 */
1355 
1356 ////////////////////////////////////////////////////////////////////////////////
1357 /// Constructor.
1358 
1360 {
1361  fItem = new TObject *[MaxIndex()+1];
1362  memset(fItem, 0, (MaxIndex()+1)*sizeof(TObject*));
1363 
1364  R__ASSERT(fItem != 0);
1365  if (obj != 0)
1366  fItem[++fLast] = (TObject*)obj; // cast const away
1367 }
1368 
1369 ////////////////////////////////////////////////////////////////////////////////
1370 /// Destructor.
1371 
1373 {
1374  delete [] fItem;
1375 }
1376 
1377 ////////////////////////////////////////////////////////////////////////////////
1378 /// Add the object OBJ to the leaf node, inserting it at location INDEX
1379 /// in the fItem array.
1380 
1381 void TBtLeafNode::Add(const TObject *obj, Int_t index)
1382 {
1383  R__ASSERT(obj->IsSortable());
1384  R__ASSERT(0 <= index && index <= fLast+1);
1385  R__ASSERT(fLast <= MaxIndex());
1386  for (Int_t i = fLast+1; i > index ; i--)
1387  fItem[i] = fItem[i-1];
1388  fItem[index] = (TObject *)obj;
1389  fLast++;
1390 
1391  // check for overflow
1392  if (fParent == 0)
1393  fTree->IncrNofKeys();
1394  else
1395  fParent->IncrNofKeys(this);
1396 
1397  if (IsFull()) {
1398  // it's full; tell parent node
1399  if (fParent == 0) {
1400  // this occurs when this leaf is the only node in the
1401  // btree, and this->fTree->fRoot == this
1402  R__CHECK(fTree->fRoot == this);
1403  // in which case we inform the btree, which can be
1404  // considered the parent of this node
1405  fTree->RootIsFull();
1406  } else {
1407  // the parent is responsible for splitting/balancing subnodes
1408  fParent->IsFull(this);
1409  }
1410  }
1411 }
1412 
1413 ////////////////////////////////////////////////////////////////////////////////
1414 /// A convenience function, does not worry about the element in
1415 /// the parent, simply moves elements from SRC[start] to SRC[stop]
1416 /// into the current array.
1417 /// This should never create a full node.
1418 /// That is, it is not used anywhere where THIS could possibly be
1419 /// near full.
1420 /// Does NOT handle nofKeys.
1421 
1423 {
1424  if (start > stop)
1425  return;
1426  R__ASSERT(0 <= start && start <= src->fLast);
1427  R__ASSERT(0 <= stop && stop <= src->fLast);
1428  R__ASSERT(fLast + stop - start + 1 < MaxIndex()); // full-node check
1429  for (Int_t i = start; i <= stop; i++)
1430  fItem[++fLast] = src->fItem[i];
1431  R__CHECK(fLast < MaxIndex());
1432 }
1433 
1434 ////////////////////////////////////////////////////////////////////////////////
1435 /// Never called from anywhere where it might fill up THIS
1436 /// does NOT handle nofKeys.
1437 
1439 {
1440  R__ASSERT(obj->IsSortable());
1441  fItem[++fLast] = obj;
1442  R__CHECK(fLast < MaxIndex());
1443 }
1444 
1445 ////////////////////////////////////////////////////////////////////////////////
1446 /// THIS has more than LEFTSIB; move some items from THIS to LEFTSIB.
1447 
1449 {
1450  R__ASSERT(Vsize() >= leftsib->Psize());
1451  Int_t newThisSize = (Vsize() + leftsib->Psize())/2;
1452  Int_t noFromThis = Psize() - newThisSize;
1453  PushLeft(noFromThis, leftsib, pidx);
1454 }
1455 
1456 ////////////////////////////////////////////////////////////////////////////////
1457 /// THIS has more than RIGHTSIB; move some items from THIS to RIGHTSIB.
1458 
1460 {
1461  R__ASSERT(Psize() >= rightsib->Vsize());
1462  Int_t newThisSize = (Psize() + rightsib->Vsize())/2;
1463  Int_t noFromThis = Psize() - newThisSize;
1464  PushRight(noFromThis, rightsib, pidx);
1465 }
1466 
1467 ////////////////////////////////////////////////////////////////////////////////
1468 /// PITEM is the parent item whose key will change when keys are shifted
1469 /// from one LeafNode to the other.
1470 
1472 {
1473  if (Psize() < rightsib->Vsize())
1474  rightsib->BalanceWithLeft(this, pidx);
1475  else
1476  BalanceWithRight(rightsib, pidx);
1477 }
1478 
1479 ////////////////////////////////////////////////////////////////////////////////
1480 /// WHAT was not in any inner node; it is either here, or it's
1481 /// not in the tree.
1482 
1484 {
1485  for (Int_t i = 0; i <= fLast; i++) {
1486  if (fItem[i]->Compare(what) == 0)
1487  return i;
1488  if (fItem[i]->Compare(what) > 0)
1489  return -1;
1490  }
1491  return -1;
1492 }
1493 
1494 ////////////////////////////////////////////////////////////////////////////////
1495 /// Return the first node.
1496 
1498 {
1499  return this;
1500 }
1501 
1502 ////////////////////////////////////////////////////////////////////////////////
1503 /// WHAT was not in any inner node; it is either here, or it's
1504 /// not in the tree.
1505 
1507 {
1508  R__ASSERT(what->IsSortable());
1509  for (Int_t i = 0; i <= fLast; i++) {
1510  if (fItem[i]->Compare(what) == 0) {
1511  *which = this;
1512  *where = i;
1513  return fItem[i];
1514  }
1515  if (fItem[i]->Compare(what) > 0) {
1516  *which = this;
1517  *where = i;
1518  return 0;
1519  }
1520  }
1521  *which = this;
1522  *where = fLast+1;
1523  return 0;
1524 }
1525 
1526 ////////////////////////////////////////////////////////////////////////////////
1527 /// Returns a number in the range 0 to MaxIndex().
1528 
1530 {
1531  for (Int_t i = 0; i <= fLast; i++) {
1532  if (fItem[i] == that)
1533  return i;
1534  }
1535  R__CHECK(0);
1536  return -1;
1537 }
1538 
1539 ////////////////////////////////////////////////////////////////////////////////
1540 /// return the last node.
1541 
1543 {
1544  return this;
1545 }
1546 
1547 ////////////////////////////////////////////////////////////////////////////////
1548 /// Merge.
1549 
1551 {
1552  R__ASSERT(Psize() + rightsib->Vsize() < MaxPsize());
1553  rightsib->PushLeft(rightsib->Psize(), this, pidx);
1554  Append(fParent->GetKey(pidx));
1555  fParent->SetNofKeys(pidx-1, NofKeys());
1556  fParent->RemoveItem(pidx);
1557  delete rightsib;
1558 }
1559 
1560 ////////////////////////////////////////////////////////////////////////////////
1561 /// Return the number of keys.
1562 
1564 {
1565  return 1;
1566 }
1567 
1568 ////////////////////////////////////////////////////////////////////////////////
1569 /// Return the number of keys.
1570 
1572 {
1573  return Psize();
1574 }
1575 
1576 //______________________________________________________________________________
1577 //void TBtLeafNode::PrintOn(std::ostream& out) const
1578 //{
1579 // out << " < ";
1580 // for (Int_t i = 0; i <= fLast; i++)
1581 // out << *fItem[i] << " " ;
1582 // out << "> ";
1583 //}
1584 
1585 ////////////////////////////////////////////////////////////////////////////////
1586 /// noFromThis==1 => moves the parent item into the leftsib,
1587 /// and the first item in this's array into the parent item.
1588 
1589 void TBtLeafNode::PushLeft(Int_t noFromThis, TBtLeafNode *leftsib, Int_t pidx)
1590 {
1591  R__ASSERT(noFromThis > 0 && noFromThis <= Psize());
1592  R__ASSERT(noFromThis + leftsib->Psize() < MaxPsize());
1593  R__ASSERT(fParent->GetTree(pidx) == this);
1594  leftsib->Append(fParent->GetKey(pidx));
1595  if (noFromThis > 1)
1596  leftsib->AppendFrom(this, 0, noFromThis-2);
1597  fParent->SetKey(pidx, fItem[noFromThis-1]);
1598  ShiftLeft(noFromThis);
1599  fParent->SetNofKeys(pidx-1, leftsib->NofKeys());
1600  fParent->SetNofKeys(pidx, NofKeys());
1601 }
1602 
1603 ////////////////////////////////////////////////////////////////////////////////
1604 /// noFromThis==1 => moves the parent item into the
1605 /// rightsib, and the last item in this's array into the parent
1606 /// item.
1607 
1608 void TBtLeafNode::PushRight(Int_t noFromThis, TBtLeafNode *rightsib, Int_t pidx)
1609 {
1610  R__ASSERT(noFromThis > 0 && noFromThis <= Psize());
1611  R__ASSERT(noFromThis + rightsib->Psize() < MaxPsize());
1612  R__ASSERT(fParent->GetTree(pidx) == rightsib);
1613  // The operation is five steps:
1614  // Step I. Make room for the incoming keys in RIGHTSIB.
1615  // Step II. Move the key in the parent into RIGHTSIB.
1616  // Step III. Move the items from THIS into RIGHTSIB.
1617  // Step IV. Move the item from THIS into the parent.
1618  // Step V. Update the length of THIS.
1619  //
1620  // Step I.: make space for noFromThis items
1621  //
1622  Int_t start = fLast - noFromThis + 1;
1623  Int_t tgt, src;
1624  tgt = rightsib->fLast + noFromThis;
1625  src = rightsib->fLast;
1626  rightsib->fLast = tgt;
1627  while (src >= 0)
1628  rightsib->fItem[tgt--] = rightsib->fItem[src--];
1629 
1630  // Step II. Move the key from the parent into place
1631  rightsib->fItem[tgt--] = fParent->GetKey(pidx);
1632 
1633  // Step III.Move the items from THIS into RIGHTSIB
1634  for (Int_t i = fLast; i > start; i--)
1635  rightsib->fItem[tgt--] = fItem[i];
1636  R__CHECK(tgt == -1);
1637 
1638  // Step IV.
1639  fParent->SetKey(pidx, fItem[start]);
1640 
1641  // Step V.
1642  fLast -= noFromThis;
1643 
1644  // Step VI. update nofKeys
1645  fParent->SetNofKeys(pidx-1, NofKeys());
1646  fParent->SetNofKeys(pidx, rightsib->NofKeys());
1647 }
1648 
1649 ////////////////////////////////////////////////////////////////////////////////
1650 /// Remove an element.
1651 
1653 {
1654  R__ASSERT(index >= 0 && index <= fLast);
1655  for (Int_t to = index; to < fLast; to++)
1656  fItem[to] = fItem[to+1];
1657  fLast--;
1658  if (fParent == 0)
1659  fTree->DecrNofKeys();
1660  else
1661  fParent->DecrNofKeys(this);
1662  if (IsLow()) {
1663  if (fParent == 0) {
1664  // then this is the root; when no keys left, inform the tree
1665  if (Psize() == 0)
1666  fTree->RootIsEmpty();
1667  } else
1668  fParent->IsLow(this);
1669  }
1670 }
1671 
1672 ////////////////////////////////////////////////////////////////////////////////
1673 /// Shift.
1674 
1676 {
1677  if (cnt <= 0)
1678  return;
1679  for (Int_t i = cnt; i <= fLast; i++)
1680  fItem[i-cnt] = fItem[i];
1681  fLast -= cnt;
1682 }
1683 
1684 ////////////////////////////////////////////////////////////////////////////////
1685 /// This function is called only when THIS is the only descendent
1686 /// of the root node, and THIS needs to be split.
1687 /// Assumes that idx of THIS in Parent is 0.
1688 
1690 {
1691  TBtLeafNode *newnode = new TBtLeafNode(fParent);
1692  R__ASSERT(newnode != 0);
1693  fParent->Append(fItem[fLast--], newnode);
1696  BalanceWithRight(newnode, 1);
1697 }
1698 
1699 ////////////////////////////////////////////////////////////////////////////////
1700 /// Split.
1701 
1703 {
1704  R__ASSERT(fParent == rightsib->fParent);
1705  R__ASSERT(keyidx > 0 && keyidx <= fParent->fLast);
1706  Int_t nofKeys = Psize() + rightsib->Vsize();
1707  Int_t newSizeThis = nofKeys / 3;
1708  Int_t newSizeNew = (nofKeys - newSizeThis) / 2;
1709  Int_t newSizeSib = (nofKeys - newSizeThis - newSizeNew);
1710  Int_t noFromThis = Psize() - newSizeThis;
1711  Int_t noFromSib = rightsib->Vsize() - newSizeSib;
1712  R__CHECK(noFromThis >= 0);
1713  R__CHECK(noFromSib >= 1);
1714  TBtLeafNode *newNode = new TBtLeafNode(fParent);
1715  R__ASSERT(newNode != 0);
1716  fParent->AddElt(keyidx, fItem[fLast--], newNode);
1717  fParent->SetNofKeys(keyidx, 0);
1718  fParent->DecNofKeys(keyidx-1);
1719  this->PushRight(noFromThis-1, newNode, keyidx);
1720  rightsib->PushLeft(noFromSib, newNode, keyidx+1);
1721  if (fParent->IsFull())
1722  fParent->InformParent();
1723 }
TBtLeafNode(TBtInnerNode *p, const TObject *obj=0, TBtree *t=0)
Constructor.
Definition: TBtree.cxx:1359
Int_t NofKeys(Int_t idx) const
Definition: TBtree.h:399
void SetItem(Int_t i, TBtItem &itm)
Definition: TBtree.h:216
Int_t NofKeys(Int_t i) const
Return the number of keys.
Definition: TBtree.cxx:1563
TObject * At(Int_t idx) const
Definition: TBtree.h:376
friend class TBtInnerNode
Definition: TBtree.h:45
void BalanceWithLeft(TBtLeafNode *l, Int_t idx)
THIS has more than LEFTSIB; move some items from THIS to LEFTSIB.
Definition: TBtree.cxx:1448
void InformParent()
Tell the parent that we are full.
Definition: TBtree.cxx:954
const TBtree * fTree
Definition: TBtree.h:344
Int_t FindRankUp(const TBtNode *n) const
FindRankUp is FindRank in reverse.
Definition: TBtree.cxx:886
Int_t fLeafMaxIndex
Definition: TBtree.h:57
TBtItem * fItem
Definition: TBtree.h:193
Bool_t IsOnHeap() const
Definition: TObject.h:140
void ShiftLeft(Int_t cnt)
Shift.
Definition: TBtree.cxx:1675
Int_t DecNofKeys(Int_t i, Int_t n=1)
Definition: TBtree.h:414
Bool_t IsReading() const
Definition: TBuffer.h:81
void AppendFrom(TBtInnerNode *src, Int_t start, Int_t stop)
This should never create a full node that is, it is not used anywhere where THIS could possibly be ne...
Definition: TBtree.cxx:773
Leaf node of a TBtree.
Definition: TBtree.h:274
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
void Fatal(const char *location, const char *msgfmt,...)
~TBtItem()
Delete a tree item.
Definition: TBtree.cxx:526
Int_t fLeafLowWaterMark
Definition: TBtree.h:55
TIterator * MakeIterator(Bool_t dir=kIterForward) const
Returns a B-tree iterator.
Definition: TBtree.cxx:381
void SetNofKeys(Int_t i, Int_t r)
Definition: TBtree.h:404
const char Option_t
Definition: RtypesCore.h:62
TBtInnerNode(TBtInnerNode *parent, TBtree *t=0)
Create a B-tree innernode.
Definition: TBtree.cxx:684
Int_t fInnerMaxIndex
Definition: TBtree.h:56
Int_t IsAlmostFull() const
Definition: TBtree.h:259
Int_t Psize() const
Definition: TBtree.h:316
void MayNotUse(const char *method) const
Use this method to signal that a method (defined in a base class) may not be called in a derived clas...
Definition: TObject.cxx:971
Int_t MaxIndex() const
Definition: TBtree.h:252
void RemoveItem(Int_t idx)
Definition: TBtree.h:288
void Add(TObject *obj)
Add object to B-tree.
Definition: TBtree.cxx:196
virtual ~TBtree()
Delete B-tree.
Definition: TBtree.cxx:185
Abstract base class (ABC) of a TBtree node.
Definition: TBtree.h:116
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
TBtLeafNode * FirstLeafNode()
Return the first node.
Definition: TBtree.cxx:1497
TBtree * fTree
Definition: TBtree.h:129
#define R__ASSERT(e)
Definition: TError.h:98
void RootIsEmpty()
If root is empty clean up its space.
Definition: TBtree.cxx:437
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
TObject * ob
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
void Clear(Option_t *option="")
Remove all objects from B-tree.
Definition: TBtree.cxx:243
Int_t IsFull() const
Definition: TBtree.h:323
virtual TObject * Found(const TObject *obj, TBtNode **which, Int_t *where)=0
void DecrNofKeys()
Definition: TBtree.h:65
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
virtual ~TBtNode()
Delete a B-tree node.
Definition: TBtree.cxx:560
TObject * After(const TObject *obj) const
Cannot use this method since B-tree decides order.
Definition: TBtree.cxx:224
TBtNode * fRoot
Definition: TBtree.h:49
void BalanceWithRight(TBtInnerNode *r, Int_t idx)
THIS has more than RIGHTSIB.
Definition: TBtree.cxx:822
Int_t IdxAdd(const TObject &obj)
Add object and return its index in the tree.
Definition: TBtree.cxx:297
Iterator abstract base class.
Definition: TIterator.h:32
TObject Int_t at
void AddElt(TBtItem &itm, Int_t at)
Add one element.
Definition: TBtree.cxx:731
Int_t NofKeys() const
Return the number of keys.
Definition: TBtree.cxx:1571
virtual void Add(const TObject *obj, Int_t index)=0
void PushLeft(Int_t cnt, TBtInnerNode *leftsib, Int_t parentIdx)
noFromThis==1 => moves the parent item into the leftsib, and the first item in this's array into the ...
Definition: TBtree.cxx:1166
Bool_t fDirection
Definition: TBtree.h:347
Bool_t IsArgNull(const char *where, const TObject *obj) const
Returns true if object is a null pointer.
Int_t FindRank(const TObject *obj) const
Recursively look for WHAT starting in the current node.
Definition: TBtree.cxx:859
TObject * Next()
Get next object from B-tree. Returns 0 when no more objects in tree.
Definition: TBtree.cxx:635
#define SafeDelete(p)
Definition: RConfig.h:436
void SetTree(Int_t i, TBtNode *node)
Definition: TBtree.h:214
Int_t fCursor
Definition: TBtree.h:346
void Remove(Int_t idx)
Remove an element.
Definition: TBtree.cxx:1652
void Class()
Definition: Class.C:29
void MergeWithRight(TBtLeafNode *r, Int_t idx)
Merge.
Definition: TBtree.cxx:1550
#define R__CHECK(e)
Definition: TError.h:102
void Init(TClassEdit::TInterpreterLookupHelper *helper)
Definition: TClassEdit.cxx:118
void Reset()
Reset the B-tree iterator.
Definition: TBtree.cxx:622
std::map< std::string, std::string >::const_iterator iter
Definition: TAlienJob.cxx:54
TObject * Found(const TObject *obj, TBtNode **which, Int_t *where)
Recursively look for WHAT starting in the current node.
Definition: TBtree.cxx:906
Int_t IsLow() const
Definition: TBtree.h:325
Item stored in inner nodes of a TBtree.
Definition: TBtree.h:165
TBtLeafNode * LastLeafNode()
Return the last leaf node.
Definition: TBtree.cxx:1109
TIterator & operator=(const TIterator &rhs)
Overridden assignment operator.
Definition: TBtree.cxx:593
const Bool_t kIterForward
Definition: TCollection.h:43
TBtNode(Int_t isleaf, TBtInnerNode *p, TBtree *t=0)
Create a B-tree node.
Definition: TBtree.cxx:537
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:918
void BalanceWith(TBtLeafNode *n, Int_t idx)
PITEM is the parent item whose key will change when keys are shifted from one LeafNode to the other...
Definition: TBtree.cxx:1471
Int_t MaxIndex() const
Definition: TBtree.h:318
void Error(const char *location, const char *msgfmt,...)
TBtNode * fTree
Definition: TBtree.h:172
TBtLeafNode * LastLeafNode()
return the last node.
Definition: TBtree.cxx:1542
TBtItem & GetItem(Int_t i) const
Definition: TBtree.h:226
Int_t fNofKeysInTree
Definition: TBtree.h:170
virtual Bool_t IsSortable() const
Definition: TObject.h:139
void MergeWithRight(TBtInnerNode *r, Int_t idx)
Merge the 2 part of the tree.
Definition: TBtree.cxx:1117
static const char * what
Definition: stlLoader.cc:6
Int_t fOrder2
Definition: TBtree.h:52
Int_t fOrder
Definition: TBtree.h:51
friend class TBtLeafNode
Definition: TBtree.h:46
virtual TBtLeafNode * LastLeafNode()=0
void Split()
This function is called only when THIS is the only descendent of the root node, and THIS needs to be ...
Definition: TBtree.cxx:1273
Int_t Psize() const
Definition: TBtree.h:250
Int_t FindRank(const TObject *obj) const
WHAT was not in any inner node; it is either here, or it's not in the tree.
Definition: TBtree.cxx:1483
ROOT::R::TRInterface & r
Definition: Object.C:4
Int_t fCurCursor
Definition: TBtree.h:345
void PushRight(Int_t cnt, TBtLeafNode *r, Int_t parentIndex)
noFromThis==1 => moves the parent item into the rightsib, and the last item in this's array into the ...
Definition: TBtree.cxx:1608
Bool_t IsOwner() const
Definition: TCollection.h:101
virtual void Split()=0
void PushLeft(Int_t cnt, TBtLeafNode *l, Int_t parentIndex)
noFromThis==1 => moves the parent item into the leftsib, and the first item in this's array into the ...
Definition: TBtree.cxx:1589
Int_t fIsLeaf
Definition: TBtree.h:130
TBtNode * GetTree(Int_t i) const
Definition: TBtree.h:224
void Append(TObject *obj, TBtNode *n)
Never called from anywhere where it might fill up THIS.
Definition: TBtree.cxx:787
void AppendFrom(TBtLeafNode *src, Int_t start, Int_t stop)
A convenience function, does not worry about the element in the parent, simply moves elements from SR...
Definition: TBtree.cxx:1422
TObject * fKey
Definition: TBtree.h:171
void BalanceWithRight(TBtLeafNode *r, Int_t idx)
THIS has more than RIGHTSIB; move some items from THIS to RIGHTSIB.
Definition: TBtree.cxx:1459
TObject * operator*() const
Return current object or nullptr.
Definition: TBtree.cxx:671
TClass * IsA() const
Int_t NofKeys() const
Number of key.
Definition: TBtree.cxx:1132
unsigned int UInt_t
Definition: RtypesCore.h:42
void DecrNofKeys(TBtNode *np)
THAT is a child of THIS that has just shrunk by 1.
Definition: TBtree.cxx:846
void RootIsFull()
The root of the tree is full.
Definition: TBtree.cxx:426
Int_t Vsize() const
Definition: TBtree.h:434
Int_t fLast
Definition: TBtree.h:123
TLine * l
Definition: textangle.C:4
Int_t fSize
Definition: TCollection.h:63
void Append(TObject *obj)
Never called from anywhere where it might fill up THIS does NOT handle nofKeys.
Definition: TBtree.cxx:1438
void IncrNofKeys(TBtNode *np)
THAT is a child of THIS that has just grown by 1.
Definition: TBtree.cxx:928
virtual void SetByteCount(UInt_t cntpos, Bool_t packInVersion=kFALSE)=0
void Init(Int_t i)
Initialize a B-tree.
Definition: TBtree.cxx:340
void Reset(Detail::TBranchProxy *x)
void Remove(Int_t idx)
Remove an element.
Definition: TBtree.cxx:1229
virtual void Remove(Int_t index)=0
virtual TBtree * GetParentTree() const
Definition: TBtree.h:138
Int_t IsAlmostFull() const
Definition: TBtree.h:324
virtual Int_t FindRank(const TObject *obj) const =0
TObject * operator[](Int_t i) const
return an element.
Definition: TBtree.cxx:1143
TObject * Before(const TObject *obj) const
May not use this method since B-tree decides order.
Definition: TBtree.cxx:233
~TBtLeafNode()
Destructor.
Definition: TBtree.cxx:1372
~TBtInnerNode()
Constructor.
Definition: TBtree.cxx:708
static void GarbageCollect(TObject *obj)
Add to the list of things to be cleaned up.
Int_t IsLow() const
Definition: TBtree.h:260
Iterator of btree.
Definition: TBtree.h:338
TObject * GetKey(Int_t i) const
Definition: TBtree.h:225
Int_t Rank(const TObject *obj) const
Returns the rank of the object in the tree.
Definition: TBtree.cxx:389
virtual Int_t GetSize() const
Definition: TCollection.h:95
void SplitWith(TBtLeafNode *r, Int_t idx)
Split.
Definition: TBtree.cxx:1702
TBtreeIter()
Definition: TBtree.h:349
Int_t IsFull() const
Definition: TBtree.h:257
TObject * Remove(TObject *obj)
Remove an object from the tree.
Definition: TBtree.cxx:404
Int_t IncNofKeys(Int_t i, Int_t n=1)
Definition: TBtree.h:409
void IncrNofKeys()
Definition: TBtree.h:64
void SetKey(Int_t i, TObject *obj)
Definition: TBtree.h:215
void Delete(Option_t *option="")
Remove all objects from B-tree AND delete all heap based objects.
Definition: TBtree.cxx:256
void BalanceWithLeft(TBtInnerNode *l, Int_t idx)
THIS has more than LEFTSIB.
Definition: TBtree.cxx:808
ClassImp(TBtree) TBtree
Create a B-tree of certain order (by default 3).
Definition: TBtree.cxx:171
void PushRight(Int_t cnt, TBtInnerNode *rightsib, Int_t parentIdx)
The operation is three steps:
Definition: TBtree.cxx:1185
Bool_t operator!=(const TIterator &aIter) const
This operator compares two TIterator objects.
Definition: TBtree.cxx:651
#define name(a, b)
Definition: linkTestLib0.cpp:5
Mother of all ROOT objects.
Definition: TObject.h:58
void RemoveItem(Int_t idx)
Remove an item.
Definition: TBtree.cxx:1240
Int_t Vsize() const
Definition: TBtree.h:419
TObject * Found(const TObject *obj, TBtNode **which, Int_t *where)
WHAT was not in any inner node; it is either here, or it's not in the tree.
Definition: TBtree.cxx:1506
Int_t IndexOf(const TObject *obj) const
Returns a number in the range 0 to MaxIndex().
Definition: TBtree.cxx:1529
TBtLeafNode * FirstLeafNode()
Return the first leaf node.
Definition: TBtree.cxx:898
Int_t MaxPsize() const
Definition: TBtree.h:253
void ShiftLeft(Int_t cnt)
Shift to the left.
Definition: TBtree.cxx:1259
Int_t Compare(const void *item1, const void *item2)
Int_t IndexOf(const TBtNode *n) const
Returns a number in the range 0 to this->fLast 0 is returned if THAT == fTree[0]. ...
Definition: TBtree.cxx:942
virtual Int_t Compare(const TObject *obj) const
Compare abstract method.
Definition: TObject.cxx:218
void SplitWith(TBtInnerNode *r, Int_t idx)
THIS and SIB are too full; create a NEWNODE, and balance the number of keys between the three of them...
Definition: TBtree.cxx:1312
TObject * FindObject(const char *name) const
Find object using its name (see object's GetName()).
Definition: TBtree.cxx:271
Int_t GetNofKeys(Int_t i) const
Definition: TBtree.h:393
virtual TBtLeafNode * FirstLeafNode()=0
const Bool_t kTRUE
Definition: Rtypes.h:91
TObject * obj
Inner node of a TBtree.
Definition: TBtree.h:190
void Split()
This function is called only when THIS is the only descendent of the root node, and THIS needs to be ...
Definition: TBtree.cxx:1689
virtual Int_t NofKeys() const =0
TObject ** fItem
Definition: TBtree.h:279
Int_t fInnerLowWaterMark
Definition: TBtree.h:54
const Int_t n
Definition: legend1.C:16
B-tree class.
Definition: TBtree.h:42
const char * cnt
Definition: TXMLSetup.cxx:75
Int_t MaxPsize() const
Definition: TBtree.h:319
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
TBtInnerNode * fParent
Definition: TBtree.h:128
void Add(const TObject *obj, Int_t idx)
This is called only from TBtree::Add().
Definition: TBtree.cxx:721
void Add(const TObject *obj, Int_t idx)
Add the object OBJ to the leaf node, inserting it at location INDEX in the fItem array.
Definition: TBtree.cxx:1381
void BalanceWith(TBtInnerNode *n, int idx)
PINDX is the index of the parent item whose key will change when keys are shifted from one InnerNode ...
Definition: TBtree.cxx:835
TBtItem()
sub-tree
Definition: TBtree.cxx:492
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:904