1 : // $Id: btree.h 37 2007-04-27 12:13:27Z tb $
2 : /** \file btree.h
3 : * Contains the main B+ tree implementation template class btree.
4 : */
5 :
6 : /*
7 : * STX B+ Tree Template Classes v0.7
8 : * Copyright (C) 2007 Timo Bingmann
9 : *
10 : * This library is free software; you can redistribute it and/or modify it
11 : * under the terms of the GNU Lesser General Public License as published by the
12 : * Free Software Foundation; either version 2.1 of the License, or (at your
13 : * option) any later version.
14 : *
15 : * This library is distributed in the hope that it will be useful, but WITHOUT
16 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 : * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
18 : * for more details.
19 : *
20 : * You should have received a copy of the GNU Lesser General Public License
21 : * along with this library; if not, write to the Free Software Foundation,
22 : * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 : */
24 :
25 : #ifndef _STX_BTREE_H_
26 : #define _STX_BTREE_H_
27 :
28 : // *** Required Headers from the STL
29 :
30 : #include <functional>
31 : #include <algorithm>
32 : #include <istream>
33 : #include <ostream>
34 : #include <assert.h>
35 :
36 : // *** Debugging Macros
37 :
38 : #ifdef BTREE_DEBUG
39 :
40 : #include <iostream>
41 :
42 : /// Print out debug information to std::cout if BTREE_DEBUG is defined.
43 : #define BTREE_PRINT(x) do { if (debug) (std::cout << x); } while(0)
44 :
45 : /// Assertion only if BTREE_DEBUG is defined. This is not used in verify().
46 : #define BTREE_ASSERT(x) do { assert(x); } while(0)
47 :
48 : #else
49 :
50 : /// Print out debug information to std::cout if BTREE_DEBUG is defined.
51 : #define BTREE_PRINT(x) do { } while(0)
52 :
53 : /// Assertion only if BTREE_DEBUG is defined. This is not used in verify().
54 : #define BTREE_ASSERT(x) do { } while(0)
55 :
56 : #endif
57 :
58 : /// The maximum of a and b. Used in some compile-time formulas.
59 : #define BTREE_MAX(a,b) ((a) < (b) ? (b) : (a))
60 :
61 : /// STX - Some Template Extensions namespace
62 : namespace stx {
63 :
64 : /** Generates default traits for a B+ tree used as a set. It estimates leaf and
65 : * inner node sizes by assuming a cache line size of 256 bytes. */
66 : template <typename _Key>
67 : struct btree_default_set_traits
68 : {
69 : /// If true, the tree will self verify it's invariants after each insert()
70 : /// or erase(). The header must have been compiled with BTREE_DEBUG defined.
71 : static const bool selfverify = false;
72 :
73 : /// If true, the tree will print out debug information and a tree dump
74 : /// during insert() or erase() operation. The header must have been
75 : /// compiled with BTREE_DEBUG defined and key_type must be std::ostream
76 : /// printable.
77 : static const bool debug = false;
78 :
79 : /// Number of slots in each leaf of the tree. Estimated so that each node
80 : /// has a size of about 256 bytes.
81 : static const int leafslots = BTREE_MAX( 8, 256 / (sizeof(_Key)) );
82 :
83 : /// Number of slots in each inner node of the tree. Estimated so that each node
84 : /// has a size of about 256 bytes.
85 : static const int innerslots = BTREE_MAX( 8, 256 / (sizeof(_Key) + sizeof(void*)) );
86 : };
87 :
88 : /** Generates default traits for a B+ tree used as a map. It estimates leaf and
89 : * inner node sizes by assuming a cache line size of 256 bytes. */
90 : template <typename _Key, typename _Data>
91 : struct btree_default_map_traits
92 : {
93 : /// If true, the tree will self verify it's invariants after each insert()
94 : /// or erase(). The header must have been compiled with BTREE_DEBUG defined.
95 : static const bool selfverify = false;
96 :
97 : /// If true, the tree will print out debug information and a tree dump
98 : /// during insert() or erase() operation. The header must have been
99 : /// compiled with BTREE_DEBUG defined and key_type must be std::ostream
100 : /// printable.
101 : static const bool debug = false;
102 :
103 : /// Number of slots in each leaf of the tree. Estimated so that each node
104 : /// has a size of about 256 bytes.
105 : static const int leafslots = BTREE_MAX( 8, 256 / (sizeof(_Key) + sizeof(_Data)) );
106 :
107 : /// Number of slots in each inner node of the tree. Estimated so that each node
108 : /// has a size of about 256 bytes.
109 : static const int innerslots = BTREE_MAX( 8, 256 / (sizeof(_Key) + sizeof(void*)) );
110 : };
111 :
112 : /** @brief Basic class implementing a base B+ tree data structure in memory.
113 : *
114 : * The base implementation of a memory B+ tree. It is based on the
115 : * implementation in Cormen's Introduction into Algorithms, Jan Jannink's paper
116 : * and other algorithm resources. Almost all STL-required function calls are
117 : * implemented. The asymptotic time requirements of the STL are not always
118 : * fulfilled in theory, however in practice this B+ tree performs better than a
119 : * red-black tree by using more memory. The insertion function splits the nodes
120 : * on the recursion unroll. Erase is largely based on Jannink's ideas.
121 : *
122 : * This class is specialized into btree_set, btree_multiset, btree_map and
123 : * btree_multimap using default template parameters and facade functions.
124 : */
125 : template <typename _Key, typename _Data,
126 : typename _Value = std::pair<_Key, _Data>,
127 : typename _Compare = std::less<_Key>,
128 : typename _Traits = btree_default_map_traits<_Key, _Data>,
129 : bool _Duplicates = false>
130 : class btree
131 : {
132 : public:
133 : // *** Template Parameter Types
134 :
135 : /// First template parameter: The key type of the B+ tree. This is stored
136 : /// in inner nodes and leaves
137 : typedef _Key key_type;
138 :
139 : /// Second template parameter: The data type associated with each
140 : /// key. Stored in the B+ tree's leaves
141 : typedef _Data data_type;
142 :
143 : /// Third template parameter: Composition pair of key and data types, this
144 : /// is required by the STL standard. The B+ tree does not store key and
145 : /// data together. If value_type == key_type then the B+ tree implements a
146 : /// set.
147 : typedef _Value value_type;
148 :
149 : /// Fourth template parameter: Key comparison function object
150 : typedef _Compare key_compare;
151 :
152 : /// Fifth template parameter: Traits object used to define more parameters
153 : /// of the B+ tree
154 : typedef _Traits traits;
155 :
156 : /// Sixth template parameter: Allow duplicate keys in the B+ tree. Used to
157 : /// implement multiset and multimap.
158 : static const bool allow_duplicates = _Duplicates;
159 :
160 : public:
161 : // *** Constructed Types
162 :
163 : /// Typedef of our own type
164 : typedef btree<key_type, data_type, value_type,
165 : key_compare, traits, allow_duplicates> btree_self;
166 :
167 : /// Size type used to count keys
168 : typedef size_t size_type;
169 :
170 : /// The pair of key_type and data_type, this may be different from value_type.
171 : typedef std::pair<key_type, data_type> pair_type;
172 :
173 : public:
174 : // *** Static Constant Options and Values of the B+ Tree
175 :
176 : /// Base B+ tree parameter: The number of key/data slots in each leaf
177 : static const unsigned short leafslotmax = traits::leafslots;
178 :
179 : /// Base B+ tree parameter: The number of key slots in each inner node,
180 : /// this can differ from slots in each leaf.
181 : static const unsigned short innerslotmax = traits::innerslots;
182 :
183 : /// Computed B+ tree parameter: The minimum number of key/data slots used
184 : /// in a leaf. If fewer slots are used, the leaf will be merged or slots
185 : /// shifted from it's siblings.
186 : static const unsigned short minleafslots = (leafslotmax / 2);
187 :
188 : /// Computed B+ tree parameter: The minimum number of key slots used
189 : /// in an inner node. If fewer slots are used, the inner node will be
190 : /// merged or slots shifted from it's siblings.
191 : static const unsigned short mininnerslots = (innerslotmax / 2);
192 :
193 : /// Debug parameter: Enables expensive and thorough checking of the B+ tree
194 : /// invariants after each insert/erase operation.
195 : static const bool selfverify = traits::selfverify;
196 :
197 : /// Debug parameter: Prints out lots of debug information about how the
198 : /// algorithms change the tree. Requires the header file to be compiled
199 : /// with BTREE_PRINT and the key type must be std::ostream printable.
200 : static const bool debug = traits::debug;
201 :
202 : private:
203 : // *** Node Classes for In-Memory Nodes
204 :
205 : /// The header structure of each node in-memory. This structure is extended
206 : /// by inner_node or leaf_node.
207 : struct node
208 65 : {
209 : /// Level in the b-tree, if level == 0 -> leaf node
210 : unsigned short level;
211 :
212 : /// Number of key slotuse use, so number of valid children or data
213 : /// pointers
214 : unsigned short slotuse;
215 :
216 : /// Delayed initialisation of constructed node
217 8693 : inline void initialize(const unsigned short l)
218 : {
219 8693 : level = l;
220 8693 : slotuse = 0;
221 : }
222 :
223 : /// True if this is a leaf node
224 61849855 : inline bool isleafnode() const
225 : {
226 61849855 : return (level == 0);
227 : }
228 : };
229 :
230 : /// Extended structure of a inner node in-memory. Contains only keys and no
231 : /// data items.
232 : struct inner_node : public node
233 9 : {
234 : /// Keys of children or data pointers
235 : key_type slotkey[innerslotmax];
236 :
237 : /// Pointers to children
238 : node* childid[innerslotmax+1];
239 :
240 : /// Set variables to initial values
241 1537 : inline void initialize(const unsigned short l)
242 : {
243 1537 : node::initialize(l);
244 : }
245 :
246 : /// True if the node's slots are full
247 8191 : inline bool isfull() const
248 : {
249 8191 : return (node::slotuse == innerslotmax);
250 : }
251 :
252 : /// True if few used entries, less than half full
253 3488 : inline bool isfew() const
254 : {
255 3488 : return (node::slotuse <= mininnerslots);
256 : }
257 :
258 : /// True if node has too few entries
259 11803777 : inline bool isunderflow() const
260 : {
261 11803777 : return (node::slotuse < mininnerslots);
262 : }
263 : };
264 :
265 : /// Extended structure of a leaf node in memory. Contains pairs of keys and
266 : /// data items. Key and data slots are kept in separate arrays, because the
267 : /// key array is traversed very often compared to accessing the data items.
268 : struct leaf_node : public node
269 56 : {
270 : /// Double linked list pointers to traverse the leaves
271 : leaf_node *prevleaf;
272 :
273 : /// Double linked list pointers to traverse the leaves
274 : leaf_node *nextleaf;
275 :
276 : /// Keys of children or data pointers
277 : key_type slotkey[leafslotmax];
278 :
279 : /// Array of data
280 : data_type slotdata[leafslotmax];
281 :
282 : /// Set variables to initial values
283 7156 : inline void initialize()
284 : {
285 7156 : node::initialize(0);
286 7156 : prevleaf = nextleaf = NULL;
287 : }
288 :
289 : /// True if the node's slots are full
290 30514 : inline bool isfull() const
291 : {
292 30514 : return (node::slotuse == leafslotmax);
293 : }
294 :
295 : /// True if few used entries, less than half full
296 13759 : inline bool isfew() const
297 : {
298 13759 : return (node::slotuse <= minleafslots);
299 : }
300 :
301 : /// True if node has too few entries
302 49332010 : inline bool isunderflow() const
303 : {
304 49332010 : return (node::slotuse < minleafslots);
305 : }
306 : };
307 :
308 : private:
309 : // *** Template Magic to Convert a pair or key/data types to a value_type
310 :
311 : /// \internal For sets the second pair_type is an empty struct, so the
312 : /// value_type should only be the first.
313 : template <typename value_type, typename pair_type>
314 : struct btree_pair_to_value
315 : {
316 : /// Convert a fake pair type to just the first component
317 : inline value_type operator()(pair_type& p) const {
318 : return p.first;
319 : }
320 : /// Convert a fake pair type to just the first component
321 16316 : inline value_type operator()(const pair_type& p) const {
322 16316 : return p.first;
323 : }
324 : };
325 :
326 : /// \internal For maps value_type is the same as the pair_type
327 : template <typename value_type>
328 : struct btree_pair_to_value<value_type, value_type>
329 : {
330 : /// Identity "convert" a real pair type to just the first component
331 : inline value_type operator()(pair_type& p) const {
332 : return p;
333 : }
334 : /// Identity "convert" a real pair type to just the first component
335 0 : inline value_type operator()(const pair_type& p) const {
336 0 : return p;
337 : }
338 : };
339 :
340 : /// Using template specialization select the correct converter used by the
341 : /// iterators
342 : typedef btree_pair_to_value<value_type, pair_type> pair_to_value_type;
343 :
344 : public:
345 : // *** Iterators and Reverse Iterators
346 :
347 : class iterator;
348 : class const_iterator;
349 :
350 : /// STL-like iterator object for B+ tree items. The iterator points to a
351 : /// specific slot number in a leaf.
352 : class iterator
353 : {
354 : public:
355 : // *** Types
356 :
357 : /// The key type of the btree. Returned by key().
358 : typedef typename btree::key_type key_type;
359 :
360 : /// The data type of the btree. Returned by data().
361 : typedef typename btree::data_type data_type;
362 :
363 : /// The value type of the btree. Returned by operator*().
364 : typedef typename btree::value_type value_type;
365 :
366 : /// The pair type of the btree.
367 : typedef typename btree::pair_type pair_type;
368 :
369 : /// Reference to the value_type. Required by the reverse_iterator.
370 : typedef value_type& reference;
371 :
372 : /// Pointer to the value_type. Required by the reverse_iterator.
373 : typedef value_type* pointer;
374 :
375 : /// STL-magic iterator category
376 : typedef std::bidirectional_iterator_tag iterator_category;
377 :
378 : /// STL-magic
379 : typedef ptrdiff_t difference_type;
380 :
381 : /// Our own type
382 : typedef iterator self;
383 :
384 : private:
385 : // *** Members
386 :
387 : /// The currently referenced leaf node of the tree
388 : typename btree::leaf_node* currnode;
389 :
390 : /// Current key/data slot referenced
391 : unsigned short currslot;
392 :
393 : /// Friendly to the const_iterator, so it may access the two data items directly
394 : friend class btree<key_type, data_type, value_type, key_compare, traits, allow_duplicates>::const_iterator;
395 :
396 : /// Evil! A temporary value_type to STL-correctly deliver operator* and
397 : /// operator->
398 : mutable value_type temp_value;
399 :
400 : public:
401 : // *** Methods
402 :
403 : /// Constructor of a mutable iterator
404 51852 : inline iterator(typename btree::leaf_node *l, unsigned short s)
405 51852 : : currnode(l), currslot(s)
406 51852 : { }
407 :
408 : /// Dereference the iterator, this is not a value_type& because key and
409 : /// value are not stored together
410 9600 : inline reference operator*() const
411 : {
412 9600 : temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot],
413 : currnode->slotdata[currslot]) );
414 9600 : return temp_value;
415 : }
416 :
417 : /// Dereference the iterator. Do not use this if possible, use key()
418 : /// and data() instead. The B+ tree does not stored key and data
419 : /// together.
420 : inline pointer operator->() const
421 : {
422 : temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot],
423 : currnode->slotdata[currslot]) );
424 : return &temp_value;
425 : }
426 :
427 : /// Key of the current slot
428 17360 : inline const key_type& key() const
429 : {
430 17360 : return currnode->slotkey[currslot];
431 : }
432 :
433 : /// Writable reference to the current data object
434 0 : inline data_type& data() const
435 : {
436 0 : return currnode->slotdata[currslot];
437 : }
438 :
439 : /// Prefix++ advance the iterator to the next slot
440 23760 : inline self& operator++()
441 : {
442 23760 : if (currslot + 1 < currnode->slotuse) {
443 18365 : ++currslot;
444 : }
445 5395 : else if (currnode->nextleaf != NULL) {
446 5387 : currnode = currnode->nextleaf;
447 5387 : currslot = 0;
448 : }
449 : else {
450 : // this is end()
451 8 : currslot = currnode->slotuse;
452 : }
453 :
454 23760 : return *this;
455 : }
456 :
457 : /// Postfix++ advance the iterator to the next slot
458 : inline self operator++(int)
459 : {
460 : self tmp = *this; // copy ourselves
461 :
462 : if (currslot + 1 < currnode->slotuse) {
463 : ++currslot;
464 : }
465 : else if (currnode->nextleaf != NULL) {
466 : currnode = currnode->nextleaf;
467 : currslot = 0;
468 : }
469 : else {
470 : // this is end()
471 : currslot = currnode->slotuse;
472 : }
473 :
474 : return tmp;
475 : }
476 :
477 : /// Prefix-- backstep the iterator to the last slot
478 16000 : inline self& operator--()
479 : {
480 16000 : if (currslot > 0) {
481 13150 : --currslot;
482 : }
483 2850 : else if (currnode->prevleaf != NULL) {
484 2850 : currnode = currnode->prevleaf;
485 2850 : currslot = currnode->slotuse - 1;
486 : }
487 : else {
488 : // this is begin()
489 0 : currslot = 0;
490 : }
491 :
492 16000 : return *this;
493 : }
494 :
495 : /// Postfix-- backstep the iterator to the last slot
496 : inline self operator--(int)
497 : {
498 : self tmp = *this; // copy ourselves
499 :
500 : if (currslot > 0) {
501 : --currslot;
502 : }
503 : else if (currnode->prevleaf != NULL) {
504 : currnode = currnode->prevleaf;
505 : currslot = currnode->slotuse - 1;
506 : }
507 : else {
508 : // this is begin()
509 : currslot = 0;
510 : }
511 :
512 : return tmp;
513 : }
514 :
515 : /// Equality of iterators
516 6410 : inline bool operator==(const self& x) const
517 : {
518 6410 : return (x.currnode == currnode) && (x.currslot == currslot);
519 : }
520 :
521 : /// Inequality of iterators
522 23768 : inline bool operator!=(const self& x) const
523 : {
524 23768 : return (x.currnode != currnode) || (x.currslot != currslot);
525 : }
526 : };
527 :
528 : /// STL-like read-only iterator object for B+ tree items. The iterator
529 : /// points to a specific slot number in a leaf.
530 : class const_iterator
531 : {
532 : public:
533 : // *** Types
534 :
535 : /// The key type of the btree. Returned by key().
536 : typedef typename btree::key_type key_type;
537 :
538 : /// The data type of the btree. Returned by data().
539 : typedef typename btree::data_type data_type;
540 :
541 : /// The value type of the btree. Returned by operator*().
542 : typedef typename btree::value_type value_type;
543 :
544 : /// The pair type of the btree.
545 : typedef typename btree::pair_type pair_type;
546 :
547 : /// Reference to the value_type. Required by the reverse_iterator.
548 : typedef const value_type& reference;
549 :
550 : /// Pointer to the value_type. Required by the reverse_iterator.
551 : typedef const value_type* pointer;
552 :
553 : /// STL-magic iterator category
554 : typedef std::bidirectional_iterator_tag iterator_category;
555 :
556 : /// STL-magic
557 : typedef ptrdiff_t difference_type;
558 :
559 : /// Our own type
560 : typedef const_iterator self;
561 :
562 : private:
563 : // *** Members
564 :
565 : /// The currently referenced leaf node of the tree
566 : const typename btree::leaf_node* currnode;
567 :
568 : /// Current key/data slot referenced
569 : unsigned short currslot;
570 :
571 : /// Evil! A temporary value_type to STL-correctly deliver operator* and
572 : /// operator->
573 : mutable value_type temp_value;
574 :
575 : public:
576 : // *** Methods
577 :
578 : /// Constructor of a const iterator
579 31 : inline const_iterator(const typename btree::leaf_node *l, unsigned short s)
580 31 : : currnode(l), currslot(s)
581 31 : { }
582 :
583 : /// Copy-constructor from a mutable const iterator
584 9680 : inline const_iterator(const iterator &it)
585 9680 : : currnode(it.currnode), currslot(it.currslot)
586 9680 : { }
587 :
588 : /// Dereference the iterator. Do not use this if possible, use key()
589 : /// and data() instead. The B+ tree does not stored key and data
590 : /// together.
591 6716 : inline reference operator*() const
592 : {
593 6716 : temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot],
594 : currnode->slotdata[currslot]) );
595 6716 : return temp_value;
596 : }
597 :
598 : /// Dereference the iterator. Do not use this if possible, use key()
599 : /// and data() instead. The B+ tree does not stored key and data
600 : /// together.
601 : inline pointer operator->() const
602 : {
603 : temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot],
604 : currnode->slotdata[currslot]) );
605 : return &temp_value;
606 : }
607 :
608 : /// Key of the current slot
609 4024 : inline const key_type& key() const
610 : {
611 4024 : return currnode->slotkey[currslot];
612 : }
613 :
614 : /// Read-only reference to the current data object
615 : inline const data_type& data() const
616 : {
617 : return currnode->slotdata[currslot];
618 : }
619 :
620 : /// Prefix++ advance the iterator to the next slot
621 4796 : inline self& operator++()
622 : {
623 4796 : if (currslot + 1 < currnode->slotuse) {
624 3962 : ++currslot;
625 : }
626 834 : else if (currnode->nextleaf != NULL) {
627 822 : currnode = currnode->nextleaf;
628 822 : currslot = 0;
629 : }
630 : else {
631 : // this is end()
632 12 : currslot = currnode->slotuse;
633 : }
634 :
635 4796 : return *this;
636 : }
637 :
638 : /// Postfix++ advance the iterator to the next slot
639 : inline self operator++(int)
640 : {
641 : self tmp = *this; // copy ourselves
642 :
643 : if (currslot + 1 < currnode->slotuse) {
644 : ++currslot;
645 : }
646 : else if (currnode->nextleaf != NULL) {
647 : currnode = currnode->nextleaf;
648 : currslot = 0;
649 : }
650 : else {
651 : // this is end()
652 : currslot = currnode->slotuse;
653 : }
654 :
655 : return tmp;
656 : }
657 :
658 : /// Prefix-- backstep the iterator to the last slot
659 : inline self& operator--()
660 : {
661 : if (currslot > 0) {
662 : --currslot;
663 : }
664 : else if (currnode->prevleaf != NULL) {
665 : currnode = currnode->prevleaf;
666 : currslot = currnode->slotuse - 1;
667 : }
668 : else {
669 : // this is begin()
670 : currslot = 0;
671 : }
672 :
673 : return *this;
674 : }
675 :
676 : /// Postfix-- backstep the iterator to the last slot
677 : inline self operator--(int)
678 : {
679 : self tmp = *this; // copy ourselves
680 :
681 : if (currslot > 0) {
682 : --currslot;
683 : }
684 : else if (currnode->prevleaf != NULL) {
685 : currnode = currnode->prevleaf;
686 : currslot = currnode->slotuse - 1;
687 : }
688 : else {
689 : // this is begin()
690 : currslot = 0;
691 : }
692 :
693 : return tmp;
694 : }
695 :
696 : /// Equality of iterators
697 4842 : inline bool operator==(const self& x) const
698 : {
699 4842 : return (x.currnode == currnode) && (x.currslot == currslot);
700 : }
701 :
702 : /// Inequality of iterators
703 3367 : inline bool operator!=(const self& x) const
704 : {
705 3367 : return (x.currnode != currnode) || (x.currslot != currslot);
706 : }
707 : };
708 :
709 : /// create mutable reverse iterator by using STL magic
710 : typedef std::reverse_iterator<iterator> reverse_iterator;
711 :
712 : /// create constant reverse iterator by using STL magic
713 : typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
714 :
715 : public:
716 : // *** Small Statistics Structure
717 :
718 : /** A small struct containing basic statistics about the B+ tree. It can be
719 : * fetched using get_stats(). */
720 : struct tree_stats
721 : {
722 : /// Number of items in the B+ tree
723 : size_type itemcount;
724 :
725 : /// Number of leaves in the B+ tree
726 : size_type leaves;
727 :
728 : /// Number of inner nodes in the B+ tree
729 : size_type innernodes;
730 :
731 : /// Base B+ tree parameter: The number of key/data slots in each leaf
732 : static const unsigned short leafslots = btree_self::leafslotmax;
733 :
734 : /// Base B+ tree parameter: The number of key slots in each inner node.
735 : static const unsigned short innerslots = btree_self::innerslotmax;
736 :
737 : /// Zero initialized
738 66713 : inline tree_stats()
739 : : itemcount(0),
740 66713 : leaves(0), innernodes(0)
741 66713 : {
742 : }
743 :
744 : /// Return the total number of nodes
745 : inline size_type nodes() const
746 : {
747 : return innernodes + leaves;
748 : }
749 :
750 : /// Return the average fill of leaves
751 : inline double avgfill_leaves() const
752 : {
753 : return static_cast<double>(itemcount) / (leaves * leafslots);
754 : }
755 : };
756 :
757 : private:
758 : // *** Tree Object Data Members
759 :
760 : /// Pointer to the B+ tree's root node, either leaf or inner node
761 : node* root;
762 :
763 : /// Pointer to first leaf in the double linked leaf chain
764 : leaf_node *headleaf;
765 :
766 : /// Pointer to last leaf in the double linked leaf chain
767 : leaf_node *tailleaf;
768 :
769 : /// Other small statistics about the B+ tree
770 : tree_stats stats;
771 :
772 : /// Key comparison object. More comparison functions are generated from
773 : /// this < relation.
774 : key_compare key_less;
775 :
776 : public:
777 : // *** Constructors and Destructor
778 :
779 : /// Default constructor initializing an empty B+ tree with the standard key
780 : /// comparison function
781 15 : inline btree()
782 15 : : root(NULL), headleaf(NULL), tailleaf(NULL)
783 15 : {
784 : }
785 :
786 : /// Constructor initializing an empty B+ tree with a special key
787 : /// comparison object
788 1 : inline btree(const key_compare &kcf)
789 : : root(NULL), headleaf(NULL), tailleaf(NULL),
790 1 : key_less(kcf)
791 1 : {
792 : }
793 :
794 : /// Constructor initializing a B+ tree with the range [first,last)
795 : template <class InputIterator>
796 : inline btree(InputIterator first, InputIterator last)
797 : : root(NULL), headleaf(NULL), tailleaf(NULL)
798 : {
799 : insert(first, last);
800 : }
801 :
802 : /// Constructor initializing a B+ tree with the range [first,last) and a
803 : /// special key comparison object
804 : template <class InputIterator>
805 : inline btree(InputIterator first, InputIterator last, const key_compare &kcf)
806 : : root(NULL), headleaf(NULL), tailleaf(NULL),
807 : key_less(kcf)
808 : {
809 : insert(first, last);
810 : }
811 :
812 : /// Frees up all used B+ tree memory pages
813 18 : inline ~btree()
814 : {
815 18 : clear();
816 : }
817 :
818 : /// Fast swapping of two identical B+ tree objects.
819 : void swap(btree_self& from)
820 : {
821 : std::swap(root, from.root);
822 : std::swap(headleaf, from.headleaf);
823 : std::swap(tailleaf, from.tailleaf);
824 : std::swap(stats, from.stats);
825 : std::swap(key_less, from.key_less);
826 : }
827 :
828 : public:
829 : // *** Key and Value Comparison Function Objects
830 :
831 : /// Function class to compare value_type objects. Required by the STL
832 : class value_compare
833 : {
834 : protected:
835 : /// Key comparison function from the template parameter
836 : key_compare key_comp;
837 :
838 : /// Constructor called from btree::value_comp()
839 0 : inline value_compare(key_compare kc)
840 0 : : key_comp(kc)
841 0 : { }
842 :
843 : /// Friendly to the btree class so it may call the constructor
844 : friend class btree<key_type, data_type, value_type, key_compare, traits, allow_duplicates>;
845 :
846 : public:
847 : /// Function call "less"-operator resulting in true if x < y.
848 : inline bool operator()(const value_type& x, const value_type& y) const
849 : {
850 : return key_comp(x.first, y.first);
851 : }
852 : };
853 :
854 : /// Constant access to the key comparison object sorting the B+ tree
855 3 : inline key_compare key_comp() const
856 : {
857 3 : return key_less;
858 : }
859 :
860 : /// Constant access to a constructed value_type comparison object. Required
861 : /// by the STL
862 0 : inline value_compare value_comp() const
863 : {
864 0 : return value_compare(key_less);
865 : }
866 :
867 : private:
868 : // *** Convenient Key Comparison Functions Generated From key_less
869 :
870 : /// True if a <= b ? constructed from key_less()
871 395638602 : inline bool key_lessequal(const key_type &a, const key_type b) const
872 : {
873 395638602 : return !key_less(b, a);
874 : }
875 :
876 : /// True if a > b ? constructed from key_less()
877 : inline bool key_greater(const key_type &a, const key_type &b) const
878 : {
879 : return key_less(b, a);
880 : }
881 :
882 : /// True if a >= b ? constructed from key_less()
883 49244640 : inline bool key_greaterequal(const key_type &a, const key_type b) const
884 : {
885 49244640 : return !key_less(a, b);
886 : }
887 :
888 : /// True if a == b ? constructed from key_less(). This requires the <
889 : /// relation to be a total order, otherwise the B+ tree cannot be sorted.
890 52455581 : inline bool key_equal(const key_type &a, const key_type &b) const
891 : {
892 52455581 : return !key_less(a, b) && !key_less(b, a);
893 : }
894 :
895 : private:
896 : // *** Node Object Allocation and Deallocation Functions
897 :
898 : /// Allocate and initialize a leaf node
899 7156 : inline leaf_node* allocate_leaf()
900 : {
901 7156 : leaf_node* n = new leaf_node;
902 7156 : n->initialize();
903 7156 : stats.leaves++;
904 7156 : return n;
905 : }
906 :
907 : /// Allocate and initialize an inner node
908 1537 : inline inner_node* allocate_inner(unsigned short l)
909 : {
910 1537 : inner_node* n = new inner_node;
911 1537 : n->initialize(l);
912 1537 : stats.innernodes++;
913 1537 : return n;
914 : }
915 :
916 : /// Correctly free either inner or leaf node, destructs all contained key
917 : /// and value objects
918 8693 : inline void free_node(node *n)
919 : {
920 8693 : if (n->isleafnode()) {
921 7156 : delete static_cast<leaf_node*>(n);
922 7156 : stats.leaves--;
923 : }
924 : else {
925 1537 : delete static_cast<inner_node*>(n);
926 1537 : stats.innernodes--;
927 : }
928 : }
929 :
930 : public:
931 : // *** Fast Destruction of the B+ Tree
932 :
933 : /// Frees all key/data pairs and all nodes of the tree
934 20 : void clear()
935 : {
936 20 : if (root)
937 : {
938 17 : clear_recursive(root);
939 17 : free_node(root);
940 :
941 17 : root = NULL;
942 17 : headleaf = tailleaf = NULL;
943 :
944 17 : stats = tree_stats();
945 : }
946 :
947 20 : BTREE_ASSERT(stats.itemcount == 0);
948 : }
949 :
950 : private:
951 : /// Recursively free up nodes
952 2676 : void clear_recursive(node *n)
953 : {
954 2676 : if (n->isleafnode())
955 : {
956 2273 : leaf_node *leafnode = static_cast<leaf_node*>(n);
957 :
958 2273 : for (unsigned int slot = 0; slot < leafnode->slotuse; ++slot)
959 : {
960 : // data objects are deleted by leaf_node's destructor
961 : }
962 : }
963 : else
964 : {
965 403 : inner_node *innernode = static_cast<inner_node*>(n);
966 :
967 3062 : for (unsigned short slot = 0; slot < innernode->slotuse + 1; ++slot)
968 : {
969 2659 : clear_recursive(innernode->childid[slot]);
970 5335 : free_node(innernode->childid[slot]);
971 : }
972 : }
973 : }
974 :
975 : public:
976 : // *** STL Iterator Construction Functions
977 :
978 : /// Constructs a read/data-write iterator that points to the first slot in
979 : /// the first leaf of the B+ tree.
980 9 : inline iterator begin()
981 : {
982 9 : return iterator(headleaf, 0);
983 : }
984 :
985 : /// Constructs a read/data-write iterator that points to the first invalid
986 : /// slot in the last leaf of the B+ tree.
987 22215 : inline iterator end()
988 : {
989 22215 : return iterator(tailleaf, tailleaf->slotuse);
990 : }
991 :
992 : /// Constructs a read-only constant iterator that points to the first slot
993 : /// in the first leaf of the B+ tree.
994 18 : inline const_iterator begin() const
995 : {
996 18 : return const_iterator(headleaf, 0);
997 : }
998 :
999 : /// Constructs a read-only constant iterator that points to the first
1000 : /// invalid slot in the last leaf of the B+ tree.
1001 13 : inline const_iterator end() const
1002 : {
1003 13 : return const_iterator(tailleaf, tailleaf->slotuse);
1004 : }
1005 :
1006 : /// Constructs a read/data-write reverse iterator that points to the first
1007 : /// invalid slot in the last leaf of the B+ tree. Uses STL magic.
1008 2 : inline reverse_iterator rbegin()
1009 : {
1010 2 : return reverse_iterator(end());
1011 : }
1012 :
1013 : /// Constructs a read/data-write reverse iterator that points to the first
1014 : /// slot in the first leaf of the B+ tree. Uses STL magic.
1015 2 : inline reverse_iterator rend()
1016 : {
1017 2 : return reverse_iterator(begin());
1018 : }
1019 :
1020 : /// Constructs a read-only reverse iterator that points to the first
1021 : /// invalid slot in the last leaf of the B+ tree. Uses STL magic.
1022 0 : inline const_reverse_iterator rbegin() const
1023 : {
1024 0 : return const_reverse_iterator(end());
1025 : }
1026 :
1027 : /// Constructs a read-only reverse iterator that points to the first slot
1028 : /// in the first leaf of the B+ tree. Uses STL magic.
1029 0 : inline const_reverse_iterator rend() const
1030 : {
1031 0 : return const_reverse_iterator(begin());
1032 : }
1033 :
1034 : private:
1035 : // *** B+ Tree Node Binary Search Functions
1036 :
1037 : /// Searches for the first key in the node n less or equal to key. Uses
1038 : /// binary search with an optional linear self-verification. This is a
1039 : /// template function, because the slotkey array is located at different
1040 : /// places in leaf_node and inner_node.
1041 : template <typename node_type>
1042 712539 : inline int find_lower(const node_type *n, const key_type& key) const
1043 : {
1044 712539 : if (n->slotuse == 0) return 0;
1045 :
1046 712526 : int lo = 0,
1047 712526 : hi = n->slotuse - 1;
1048 :
1049 2655710 : while(lo < hi)
1050 : {
1051 1230658 : int mid = (lo + hi) / 2;
1052 :
1053 1230658 : if (key_lessequal(key, n->slotkey[mid])) {
1054 573768 : hi = mid - 1;
1055 : }
1056 : else {
1057 656890 : lo = mid + 1;
1058 : }
1059 : }
1060 :
1061 712526 : if (hi < 0 || key_less(n->slotkey[hi], key))
1062 422444 : hi++;
1063 :
1064 : BTREE_PRINT("btree::find_lower: on " << n << " key " << key << " -> (" << lo << ") " << hi << ", ");
1065 :
1066 : // verify result using simple linear search
1067 : if (selfverify)
1068 : {
1069 712526 : int i = n->slotuse - 1;
1070 3399314 : while(i >= 0 && key_lessequal(key, n->slotkey[i]))
1071 1974262 : i--;
1072 712526 : i++;
1073 :
1074 : BTREE_PRINT("testfind: " << i << std::endl);
1075 712526 : BTREE_ASSERT(i == hi);
1076 : }
1077 : else {
1078 : BTREE_PRINT(std::endl);
1079 : }
1080 :
1081 712526 : return hi;
1082 : }
1083 :
1084 : /// Searches for the first key in the node n greater than key. Uses binary
1085 : /// search with an optional linear self-verification. This is a template
1086 : /// function, because the slotkey array is located at different places in
1087 : /// leaf_node and inner_node.
1088 : template <typename node_type>
1089 7700 : inline int find_upper(const node_type *n, const key_type& key) const
1090 : {
1091 7700 : if (n->slotuse == 0) return 0;
1092 :
1093 7700 : int lo = 0,
1094 7700 : hi = n->slotuse - 1;
1095 :
1096 30732 : while(lo < hi)
1097 : {
1098 15332 : int mid = (lo + hi) / 2;
1099 :
1100 15332 : if (key_less(key, n->slotkey[mid])) {
1101 6026 : hi = mid - 1;
1102 : }
1103 : else {
1104 9306 : lo = mid + 1;
1105 : }
1106 : }
1107 :
1108 7700 : if (hi < 0 || key_lessequal(n->slotkey[hi], key))
1109 4748 : hi++;
1110 :
1111 : BTREE_PRINT("btree::find_upper: on " << n << " key " << key << " -> (" << lo << ") " << hi << ", ");
1112 :
1113 : // verify result using simple linear search
1114 : if (selfverify)
1115 : {
1116 7700 : int i = n->slotuse - 1;
1117 36122 : while(i >= 0 && key_less(key, n->slotkey[i]))
1118 20722 : i--;
1119 7700 : i++;
1120 :
1121 : BTREE_PRINT("btree::find_upper testfind: " << i << std::endl);
1122 7700 : BTREE_ASSERT(i == hi);
1123 : }
1124 : else {
1125 : BTREE_PRINT(std::endl);
1126 : }
1127 :
1128 7700 : return hi;
1129 : }
1130 :
1131 : public:
1132 : // *** Access Functions to the Item Count
1133 :
1134 : /// Return the number of key/data pairs in the B+ tree
1135 144086 : inline size_type size() const
1136 : {
1137 144086 : return stats.itemcount;
1138 : }
1139 :
1140 : /// Returns true if there is at least one key/data pair in the B+ tree
1141 7 : inline bool empty() const
1142 : {
1143 7 : return (size() == size_type(0));
1144 : }
1145 :
1146 : /// Returns the largest possible size of the B+ Tree. This is just a
1147 : /// function required by the STL standard, the B+ Tree can hold more items.
1148 0 : inline size_type max_size() const
1149 : {
1150 0 : return size_type(-1);
1151 : }
1152 :
1153 : /// Return a const reference to the current statistics.
1154 0 : inline const struct tree_stats& get_stats() const
1155 : {
1156 0 : return stats;
1157 : }
1158 :
1159 : public:
1160 : // *** Standard Access Functions Querying the Tree by Descending to a Leaf
1161 :
1162 : /// Non-STL function checking whether a key is in the B+ tree. The same as
1163 : /// (find(k) != end()) or (count() != 0).
1164 62708 : bool exists(const key_type &key) const
1165 : {
1166 62708 : const node *n = root;
1167 :
1168 62708 : if (!n) return false;
1169 :
1170 373026 : while(!n->isleafnode())
1171 : {
1172 247610 : const inner_node *inner = static_cast<const inner_node*>(n);
1173 247610 : int slot = find_lower(inner, key);
1174 :
1175 247610 : n = inner->childid[slot];
1176 : }
1177 :
1178 62708 : const leaf_node *leaf = static_cast<const leaf_node*>(n);
1179 :
1180 62708 : int slot = find_lower(leaf, key);
1181 62708 : return key_equal(key, leaf->slotkey[slot]);
1182 : }
1183 :
1184 : /// Tries to locate a key in the B+ tree and returns an iterator to the
1185 : /// key/data slot if found. If unsuccessful it returns end().
1186 0 : iterator find(const key_type &key)
1187 : {
1188 0 : node *n = root;
1189 0 : if (!n) return end();
1190 :
1191 0 : while(!n->isleafnode())
1192 : {
1193 0 : const inner_node *inner = static_cast<const inner_node*>(n);
1194 0 : int slot = find_lower(inner, key);
1195 :
1196 0 : n = inner->childid[slot];
1197 : }
1198 :
1199 0 : leaf_node *leaf = static_cast<leaf_node*>(n);
1200 :
1201 0 : int slot = find_lower(leaf, key);
1202 0 : return key_equal(key, leaf->slotkey[slot]) ? iterator(leaf, slot) : end();
1203 : }
1204 :
1205 : /// Tries to locate a key in the B+ tree and returns an constant iterator
1206 : /// to the key/data slot if found. If unsuccessful it returns end().
1207 0 : const_iterator find(const key_type &key) const
1208 : {
1209 0 : const node *n = root;
1210 0 : if (!n) return end();
1211 :
1212 0 : while(!n->isleafnode())
1213 : {
1214 0 : const inner_node *inner = static_cast<const inner_node*>(n);
1215 0 : int slot = find_lower(inner, key);
1216 :
1217 0 : n = inner->childid[slot];
1218 : }
1219 :
1220 0 : const leaf_node *leaf = static_cast<const leaf_node*>(n);
1221 :
1222 0 : int slot = find_lower(leaf, key);
1223 0 : return key_equal(key, leaf->slotkey[slot]) ? const_iterator(leaf, slot) : end();
1224 : }
1225 :
1226 : /// Tries to locate a key in the B+ tree and returns the number of
1227 : /// identical key entries found.
1228 34720 : size_type count(const key_type &key) const
1229 : {
1230 34720 : const node *n = root;
1231 34720 : if (!n) return 0;
1232 :
1233 214767 : while(!n->isleafnode())
1234 : {
1235 145327 : const inner_node *inner = static_cast<const inner_node*>(n);
1236 145327 : int slot = find_lower(inner, key);
1237 :
1238 145327 : n = inner->childid[slot];
1239 : }
1240 :
1241 34720 : const leaf_node *leaf = static_cast<const leaf_node*>(n);
1242 :
1243 34720 : int slot = find_lower(leaf, key);
1244 34720 : size_type num = 0;
1245 :
1246 3173397 : while (leaf && key_equal(key, leaf->slotkey[slot]))
1247 : {
1248 3103957 : ++num;
1249 3103957 : if (++slot >= leaf->slotuse)
1250 : {
1251 775421 : leaf = leaf->nextleaf;
1252 775421 : slot = 0;
1253 : }
1254 : }
1255 :
1256 34720 : return num;
1257 : }
1258 :
1259 : /// Searches the B+ tree and returns an iterator to the first key less or
1260 : /// equal to the parameter. If unsuccessful it returns end().
1261 2420 : iterator lower_bound(const key_type& key)
1262 : {
1263 2420 : node *n = root;
1264 2420 : if (!n) return end();
1265 :
1266 10120 : while(!n->isleafnode())
1267 : {
1268 5280 : const inner_node *inner = static_cast<const inner_node*>(n);
1269 5280 : int slot = find_lower(inner, key);
1270 :
1271 5280 : n = inner->childid[slot];
1272 : }
1273 :
1274 2420 : leaf_node *leaf = static_cast<leaf_node*>(n);
1275 :
1276 2420 : int slot = find_lower(leaf, key);
1277 2420 : return iterator(leaf, slot);
1278 : }
1279 :
1280 : /// Searches the B+ tree and returns an constant iterator to the first key less or
1281 : /// equal to the parameter. If unsuccessful it returns end().
1282 0 : const_iterator lower_bound(const key_type& key) const
1283 : {
1284 0 : const node *n = root;
1285 0 : if (!n) return end();
1286 :
1287 0 : while(!n->isleafnode())
1288 : {
1289 0 : const inner_node *inner = static_cast<const inner_node*>(n);
1290 0 : int slot = find_lower(inner, key);
1291 :
1292 0 : n = inner->childid[slot];
1293 : }
1294 :
1295 0 : const leaf_node *leaf = static_cast<const leaf_node*>(n);
1296 :
1297 0 : int slot = find_lower(leaf, key);
1298 0 : return const_iterator(leaf, slot);
1299 : }
1300 :
1301 : /// Searches the B+ tree and returns an iterator to the first key greater
1302 : /// than the parameter. If unsuccessful it returns end().
1303 2420 : iterator upper_bound(const key_type& key)
1304 : {
1305 2420 : node *n = root;
1306 2420 : if (!n) return end();
1307 :
1308 10120 : while(!n->isleafnode())
1309 : {
1310 5280 : const inner_node *inner = static_cast<const inner_node*>(n);
1311 5280 : int slot = find_upper(inner, key);
1312 :
1313 5280 : n = inner->childid[slot];
1314 : }
1315 :
1316 2420 : leaf_node *leaf = static_cast<leaf_node*>(n);
1317 :
1318 2420 : int slot = find_upper(leaf, key);
1319 2420 : return iterator(leaf, slot);
1320 : }
1321 :
1322 : /// Searches the B+ tree and returns an constant iterator to the first key
1323 : /// greater than the parameter. If unsuccessful it returns end().
1324 0 : const_iterator upper_bound(const key_type& key) const
1325 : {
1326 0 : const node *n = root;
1327 0 : if (!n) return end();
1328 :
1329 0 : while(!n->isleafnode())
1330 : {
1331 0 : const inner_node *inner = static_cast<const inner_node*>(n);
1332 0 : int slot = find_upper(inner, key);
1333 :
1334 0 : n = inner->childid[slot];
1335 : }
1336 :
1337 0 : const leaf_node *leaf = static_cast<const leaf_node*>(n);
1338 :
1339 0 : int slot = find_upper(leaf, key);
1340 0 : return const_iterator(leaf, slot);
1341 : }
1342 :
1343 : /// Searches the B+ tree and returns both lower_bound() and upper_bound().
1344 1210 : inline std::pair<iterator, iterator> equal_range(const key_type& key)
1345 : {
1346 1210 : return std::pair<iterator, iterator>(lower_bound(key), upper_bound(key));
1347 : }
1348 :
1349 : /// Searches the B+ tree and returns both lower_bound() and upper_bound().
1350 0 : inline std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const
1351 : {
1352 0 : return std::pair<const_iterator, const_iterator>(lower_bound(key), upper_bound(key));
1353 : }
1354 :
1355 : public:
1356 : // *** B+ Tree Object Comparison Functions
1357 :
1358 : /// Equality relation of B+ trees of the same type. B+ trees of the same
1359 : /// size and equal elements (both key and data) are considered
1360 : /// equal. Beware of the random ordering of duplicate keys.
1361 5 : inline bool operator==(const btree_self &other) const
1362 : {
1363 |