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