• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files

stx/btree.h

Go to the documentation of this file.
00001 // $Id: btree.h 113 2008-09-07 15:25:51Z tb $
00006 /*
00007  * STX B+ Tree Template Classes v0.8.3
00008  * Copyright (C) 2008 Timo Bingmann
00009  *
00010  * This library is free software; you can redistribute it and/or modify it
00011  * under the terms of the GNU Lesser General Public License as published by the
00012  * Free Software Foundation; either version 2.1 of the License, or (at your
00013  * option) any later version.
00014  *
00015  * This library is distributed in the hope that it will be useful, but WITHOUT
00016  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00017  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
00018  * for more details.
00019  *
00020  * You should have received a copy of the GNU Lesser General Public License
00021  * along with this library; if not, write to the Free Software Foundation,
00022  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00023  */
00024 
00025 #ifndef _STX_BTREE_H_
00026 #define _STX_BTREE_H_
00027 
00028 // *** Required Headers from the STL
00029 
00030 #include <algorithm>
00031 #include <functional>
00032 #include <istream>
00033 #include <ostream>
00034 #include <assert.h>
00035 
00036 // *** Debugging Macros
00037 
00038 #ifdef BTREE_DEBUG
00039 
00040 #include <iostream>
00041 
00043 #define BTREE_PRINT(x)          do { if (debug) (std::cout << x); } while(0)
00044 
00046 #define BTREE_ASSERT(x)         do { assert(x); } while(0)
00047 
00048 #else
00049 
00051 #define BTREE_PRINT(x)          do { } while(0)
00052 
00054 #define BTREE_ASSERT(x)         do { } while(0)
00055 
00056 #endif
00057 
00059 #define BTREE_MAX(a,b)          ((a) < (b) ? (b) : (a))
00060 
00061 #ifndef BTREE_FRIENDS
00065 #define BTREE_FRIENDS           friend class btree_friend;
00066 #endif
00067 
00069 namespace stx {
00070 
00073 template <typename _Key>
00074 struct btree_default_set_traits
00075 {
00078     static const bool   selfverify = false;
00079 
00084     static const bool   debug = false;
00085 
00088     static const int    leafslots = BTREE_MAX( 8, 256 / (sizeof(_Key)) );
00089 
00092     static const int    innerslots = BTREE_MAX( 8, 256 / (sizeof(_Key) + sizeof(void*)) );
00093 };
00094 
00097 template <typename _Key, typename _Data>
00098 struct btree_default_map_traits
00099 {
00102     static const bool   selfverify = false;
00103 
00108     static const bool   debug = false;
00109 
00112     static const int    leafslots = BTREE_MAX( 8, 256 / (sizeof(_Key) + sizeof(_Data)) );
00113 
00116     static const int    innerslots = BTREE_MAX( 8, 256 / (sizeof(_Key) + sizeof(void*)) );
00117 };
00118 
00132 template <typename _Key, typename _Data,
00133           typename _Value = std::pair<_Key, _Data>,
00134           typename _Compare = std::less<_Key>,
00135           typename _Traits = btree_default_map_traits<_Key, _Data>,
00136           bool _Duplicates = false>
00137 class btree
00138 {
00139 public:
00140     // *** Template Parameter Types
00141 
00144     typedef _Key                        key_type;
00145 
00148     typedef _Data                       data_type;
00149 
00154     typedef _Value                      value_type;
00155 
00157     typedef _Compare                    key_compare;
00158 
00161     typedef _Traits                     traits;
00162 
00165     static const bool                   allow_duplicates = _Duplicates;
00166 
00167     // The macro BTREE_FRIENDS can be used by outside class to access the B+
00168     // tree internals. This was added for wxBTreeDemo to be able to draw the
00169     // tree.
00170     BTREE_FRIENDS
00171 
00172 public:
00173     // *** Constructed Types
00174 
00176     typedef btree<key_type, data_type, value_type,
00177                   key_compare, traits, allow_duplicates>        btree_self;
00178 
00180     typedef size_t                              size_type;
00181 
00183     typedef std::pair<key_type, data_type>      pair_type;
00184 
00185 public:
00186     // *** Static Constant Options and Values of the B+ Tree
00187 
00189     static const unsigned short         leafslotmax =  traits::leafslots;
00190 
00193     static const unsigned short         innerslotmax =  traits::innerslots;
00194 
00198     static const unsigned short minleafslots = (leafslotmax / 2);
00199 
00203     static const unsigned short mininnerslots = (innerslotmax / 2);
00204 
00207     static const bool                   selfverify = traits::selfverify;
00208 
00212     static const bool                   debug = traits::debug;
00213 
00214 private:
00215     // *** Node Classes for In-Memory Nodes
00216 
00219     struct node
00220     {
00222         unsigned short  level;
00223 
00226         unsigned short  slotuse;
00227 
00229         inline void initialize(const unsigned short l)
00230         {
00231             level = l;
00232             slotuse = 0;
00233         }
00234 
00236         inline bool isleafnode() const
00237         {
00238             return (level == 0);
00239         }
00240     };
00241 
00244     struct inner_node : public node
00245     {
00247         key_type        slotkey[innerslotmax];
00248 
00250         node*           childid[innerslotmax+1];
00251 
00253         inline void initialize(const unsigned short l)
00254         {
00255             node::initialize(l);
00256         }
00257 
00259         inline bool isfull() const
00260         {
00261             return (node::slotuse == innerslotmax);
00262         }
00263 
00265         inline bool isfew() const
00266         {
00267             return (node::slotuse <= mininnerslots);
00268         }
00269 
00271         inline bool isunderflow() const
00272         {
00273             return (node::slotuse < mininnerslots);
00274         }
00275     };
00276 
00280     struct leaf_node : public node
00281     {
00283         leaf_node       *prevleaf;
00284 
00286         leaf_node       *nextleaf;
00287 
00289         key_type        slotkey[leafslotmax];
00290 
00292         data_type       slotdata[leafslotmax];
00293 
00295         inline void initialize()
00296         {
00297             node::initialize(0);
00298             prevleaf = nextleaf = NULL;
00299         }
00300 
00302         inline bool isfull() const
00303         {
00304             return (node::slotuse == leafslotmax);
00305         }
00306 
00308         inline bool isfew() const
00309         {
00310             return (node::slotuse <= minleafslots);
00311         }
00312 
00314         inline bool isunderflow() const
00315         {
00316             return (node::slotuse < minleafslots);
00317         }
00318     };
00319 
00320 private:
00321     // *** Template Magic to Convert a pair or key/data types to a value_type
00322 
00325     template <typename value_type, typename pair_type>
00326     struct btree_pair_to_value
00327     {
00329         inline value_type operator()(pair_type& p) const {
00330             return p.first;
00331         }
00333         inline value_type operator()(const pair_type& p) const {
00334             return p.first;
00335         }
00336     };
00337 
00339     template <typename value_type>
00340     struct btree_pair_to_value<value_type, value_type>
00341     {
00343         inline value_type operator()(pair_type& p) const {
00344             return p;
00345         }
00347         inline value_type operator()(const pair_type& p) const {
00348             return p;
00349         }
00350     };
00351 
00354     typedef btree_pair_to_value<value_type, pair_type> pair_to_value_type;
00355 
00356 public:
00357     // *** Iterators and Reverse Iterators
00358 
00359     class iterator;
00360     class const_iterator;
00361     class reverse_iterator;
00362     class const_reverse_iterator;
00363 
00366     class iterator
00367     {
00368     public:
00369         // *** Types
00370 
00372         typedef typename btree::key_type                key_type;
00373 
00375         typedef typename btree::data_type               data_type;
00376 
00378         typedef typename btree::value_type              value_type;
00379 
00381         typedef typename btree::pair_type               pair_type;
00382 
00384         typedef value_type&             reference;
00385 
00387         typedef value_type*             pointer;
00388 
00390         typedef std::bidirectional_iterator_tag iterator_category;
00391 
00393         typedef ptrdiff_t               difference_type;
00394 
00396         typedef iterator                self;
00397 
00398     private:
00399         // *** Members
00400 
00402         typename btree::leaf_node*      currnode;
00403 
00405         unsigned short          currslot;
00406 
00408         friend class const_iterator;
00409 
00411         friend class reverse_iterator;
00412 
00414         friend class const_reverse_iterator;
00415 
00418         mutable value_type              temp_value;
00419 
00420         // The macro BTREE_FRIENDS can be used by outside class to access the B+
00421         // tree internals. This was added for wxBTreeDemo to be able to draw the
00422         // tree.
00423         BTREE_FRIENDS
00424 
00425     public:
00426         // *** Methods
00427 
00429         inline iterator()
00430             : currnode(NULL), currslot(0)
00431         { }
00432 
00434         inline iterator(typename btree::leaf_node *l, unsigned short s)
00435             : currnode(l), currslot(s)
00436         { }
00437 
00439         inline iterator(const reverse_iterator &it)
00440             : currnode(it.currnode), currslot(it.currslot)
00441         { }
00442 
00445         inline reference operator*() const
00446         {
00447             temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot],
00448                                                          currnode->slotdata[currslot]) );
00449             return temp_value;
00450         }
00451 
00455         inline pointer operator->() const
00456         {
00457             temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot],
00458                                                          currnode->slotdata[currslot]) );
00459             return &temp_value;
00460         }
00461 
00463         inline const key_type& key() const
00464         {
00465             return currnode->slotkey[currslot];
00466         }
00467 
00469         inline data_type& data() const
00470         {
00471             return currnode->slotdata[currslot];
00472         }
00473 
00475         inline self& operator++()
00476         {
00477             if (currslot + 1 < currnode->slotuse) {
00478                 ++currslot;
00479             }
00480             else if (currnode->nextleaf != NULL) {
00481                 currnode = currnode->nextleaf;
00482                 currslot = 0;
00483             }
00484             else {
00485                 // this is end()
00486                 currslot = currnode->slotuse;
00487             }
00488 
00489             return *this;
00490         }
00491 
00493         inline self operator++(int)
00494         {
00495             self tmp = *this;   // copy ourselves
00496 
00497             if (currslot + 1 < currnode->slotuse) {
00498                 ++currslot;
00499             }
00500             else if (currnode->nextleaf != NULL) {
00501                 currnode = currnode->nextleaf;
00502                 currslot = 0;
00503             }
00504             else {
00505                 // this is end()
00506                 currslot = currnode->slotuse;
00507             }
00508 
00509             return tmp;
00510         }
00511 
00513         inline self& operator--()
00514         {
00515             if (currslot > 0) {
00516                 --currslot;
00517             }
00518             else if (currnode->prevleaf != NULL) {
00519                 currnode = currnode->prevleaf;
00520                 currslot = currnode->slotuse - 1;
00521             }
00522             else {
00523                 // this is begin()
00524                 currslot = 0;
00525             }
00526 
00527             return *this;
00528         }
00529 
00531         inline self operator--(int)
00532         {
00533             self tmp = *this;   // copy ourselves
00534 
00535             if (currslot > 0) {
00536                 --currslot;
00537             }
00538             else if (currnode->prevleaf != NULL) {
00539                 currnode = currnode->prevleaf;
00540                 currslot = currnode->slotuse - 1;
00541             }
00542             else {
00543                 // this is begin()
00544                 currslot = 0;
00545             }
00546 
00547             return tmp;
00548         }
00549 
00551         inline bool operator==(const self& x) const
00552         {
00553             return (x.currnode == currnode) && (x.currslot == currslot);
00554         }
00555 
00557         inline bool operator!=(const self& x) const
00558         {
00559             return (x.currnode != currnode) || (x.currslot != currslot);
00560         }
00561     };
00562 
00565     class const_iterator
00566     {
00567     public:
00568         // *** Types
00569 
00571         typedef typename btree::key_type                key_type;
00572 
00574         typedef typename btree::data_type               data_type;
00575 
00577         typedef typename btree::value_type              value_type;
00578 
00580         typedef typename btree::pair_type               pair_type;
00581 
00583         typedef const value_type&               reference;
00584 
00586         typedef const value_type*               pointer;
00587 
00589         typedef std::bidirectional_iterator_tag         iterator_category;
00590 
00592         typedef ptrdiff_t               difference_type;
00593 
00595         typedef const_iterator          self;
00596 
00597     private:
00598         // *** Members
00599 
00601         const typename btree::leaf_node*        currnode;
00602 
00604         unsigned short                  currslot;
00605 
00607         friend class const_reverse_iterator;
00608 
00611         mutable value_type              temp_value;
00612 
00613         // The macro BTREE_FRIENDS can be used by outside class to access the B+
00614         // tree internals. This was added for wxBTreeDemo to be able to draw the
00615         // tree.
00616         BTREE_FRIENDS
00617 
00618     public:
00619         // *** Methods
00620 
00622         inline const_iterator()
00623             : currnode(NULL), currslot(0)
00624         { }
00625 
00627         inline const_iterator(const typename btree::leaf_node *l, unsigned short s)
00628             : currnode(l), currslot(s)
00629         { }
00630 
00632         inline const_iterator(const iterator &it)
00633             : currnode(it.currnode), currslot(it.currslot)
00634         { }
00635 
00637         inline const_iterator(const reverse_iterator &it)
00638             : currnode(it.currnode), currslot(it.currslot)
00639         { }
00640 
00642         inline const_iterator(const const_reverse_iterator &it)
00643             : currnode(it.currnode), currslot(it.currslot)
00644         { }
00645 
00649         inline reference operator*() const
00650         {
00651             temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot],
00652                                                          currnode->slotdata[currslot]) );
00653             return temp_value;
00654         }
00655 
00659         inline pointer operator->() const
00660         {
00661             temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot],
00662                                                          currnode->slotdata[currslot]) );
00663             return &temp_value;
00664         }
00665 
00667         inline const key_type& key() const
00668         {
00669             return currnode->slotkey[currslot];
00670         }
00671 
00673         inline const data_type& data() const
00674         {
00675             return currnode->slotdata[currslot];
00676         }
00677 
00679         inline self& operator++()
00680         {
00681             if (currslot + 1 < currnode->slotuse) {
00682                 ++currslot;
00683             }
00684             else if (currnode->nextleaf != NULL) {
00685                 currnode = currnode->nextleaf;
00686                 currslot = 0;
00687             }
00688             else {
00689                 // this is end()
00690                 currslot = currnode->slotuse;
00691             }
00692 
00693             return *this;
00694         }
00695 
00697         inline self operator++(int)
00698         {
00699             self tmp = *this;   // copy ourselves
00700 
00701             if (currslot + 1 < currnode->slotuse) {
00702                 ++currslot;
00703             }
00704             else if (currnode->nextleaf != NULL) {
00705                 currnode = currnode->nextleaf;
00706                 currslot = 0;
00707             }
00708             else {
00709                 // this is end()
00710                 currslot = currnode->slotuse;
00711             }
00712 
00713             return tmp;
00714         }
00715 
00717         inline self& operator--()
00718         {
00719             if (currslot > 0) {
00720                 --currslot;
00721             }
00722             else if (currnode->prevleaf != NULL) {
00723                 currnode = currnode->prevleaf;
00724                 currslot = currnode->slotuse - 1;
00725             }
00726             else {
00727                 // this is begin()
00728                 currslot = 0;
00729             }
00730 
00731             return *this;
00732         }
00733 
00735         inline self operator--(int)
00736         {
00737             self tmp = *this;   // copy ourselves
00738 
00739             if (currslot > 0) {
00740                 --currslot;
00741             }
00742             else if (currnode->prevleaf != NULL) {
00743                 currnode = currnode->prevleaf;
00744                 currslot = currnode->slotuse - 1;
00745             }
00746             else {
00747                 // this is begin()
00748                 currslot = 0;
00749             }
00750 
00751             return tmp;
00752         }
00753 
00755         inline bool operator==(const self& x) const
00756         {
00757             return (x.currnode == currnode) && (x.currslot == currslot);
00758         }
00759 
00761         inline bool operator!=(const self& x) const
00762         {
00763             return (x.currnode != currnode) || (x.currslot != currslot);
00764         }
00765     };
00766 
00769     class reverse_iterator
00770     {
00771     public:
00772         // *** Types
00773 
00775         typedef typename btree::key_type                key_type;
00776 
00778         typedef typename btree::data_type               data_type;
00779 
00781         typedef typename btree::value_type              value_type;
00782 
00784         typedef typename btree::pair_type               pair_type;
00785 
00787         typedef value_type&             reference;
00788 
00790         typedef value_type*             pointer;
00791 
00793         typedef std::bidirectional_iterator_tag iterator_category;
00794 
00796         typedef ptrdiff_t               difference_type;
00797 
00799         typedef reverse_iterator        self;
00800 
00801     private:
00802         // *** Members
00803 
00805         typename btree::leaf_node*      currnode;
00806 
00808         unsigned short          currslot;
00809 
00811         friend class iterator;
00812 
00814         friend class const_iterator;
00815 
00817         friend class const_reverse_iterator;
00818 
00821         mutable value_type              temp_value;
00822 
00823         // The macro BTREE_FRIENDS can be used by outside class to access the B+
00824         // tree internals. This was added for wxBTreeDemo to be able to draw the
00825         // tree.
00826         BTREE_FRIENDS
00827 
00828     public:
00829         // *** Methods
00830 
00832         inline reverse_iterator()
00833             : currnode(NULL), currslot(0)
00834         { }
00835 
00837         inline reverse_iterator(typename btree::leaf_node *l, unsigned short s)
00838             : currnode(l), currslot(s)
00839         { }
00840 
00842         inline reverse_iterator(const iterator &it)
00843             : currnode(it.currnode), currslot(it.currslot)
00844         { }
00845 
00848         inline reference operator*() const
00849         {
00850             BTREE_ASSERT(currslot > 0);
00851             temp_value = pair_to_value_type()( pair_type(currnode->slotkey[currslot - 1],
00852                                                          currnode->slotdata[currslot - 1]) );
00853             return temp_value;
00854         }
00855 
00859         inline pointer operator->() const
00860         {
00861             BTREE_ASSERT(currslot > 0);
00862             temp_value = pair_to_value_type()( pair_type(currnode->