• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

DS_BPlusTree.h

Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 
00006 
00007 #ifndef __B_PLUS_TREE_CPP
00008 #define __B_PLUS_TREE_CPP
00009 
00010 #include "DS_MemoryPool.h"
00011 #include "DS_Queue.h"
00012 #include <stdio.h>
00013 #include "Export.h"
00014 
00015 // Java
00016 // http://www.seanster.com/BplusTree/BplusTree.html
00017 
00018 // Overview
00019 // http://babbage.clarku.edu/~achou/cs160/B+Trees/B+Trees.htm
00020 
00021 // Deletion
00022 // http://dbpubs.stanford.edu:8090/pub/1995-19
00023 
00024 #ifdef _MSC_VER
00025 #pragma warning( push )
00026 #endif
00027 
00028 #include "RakMemoryOverride.h"
00029 
00032 namespace DataStructures
00033 {
00036         template <class KeyType, class DataType, int order>
00037         struct RAK_DLL_EXPORT Page
00038         {
00039                 // We use the same data structure for both leaf and index nodes.  
00040                 // It uses a little more memory for index nodes but reduces
00041                 // memory fragmentation, allocations, and deallocations.
00042                 bool isLeaf;
00043 
00044                 // Used for both leaf and index nodes.
00045                 // For a leaf it means the number of elements in data
00046                 // For an index it means the number of keys and is one less than the number of children pointers.
00047                 int size;
00048 
00049                 // Used for both leaf and index nodes.
00050                 KeyType keys[order];
00051 
00052                 // Used only for leaf nodes.  Data is the actual data, while next is the pointer to the next leaf (for B+)
00053                 DataType data[order];
00054                 Page<KeyType, DataType, order> *next;
00055                 Page<KeyType, DataType, order> *previous;
00056 
00057                 // Used only for index nodes.  Pointers to the children of this node.
00058                 Page *children[order+1];
00059         };
00060 
00063         template <class KeyType, class DataType, int order>
00064         class RAK_DLL_EXPORT BPlusTree
00065         {
00066         public:
00067                 struct ReturnAction
00068                 {
00069                         KeyType key1;
00070                         KeyType key2;
00071                         enum
00072                         {
00073                                 NO_ACTION,
00074                                 REPLACE_KEY1_WITH_KEY2,
00075                                 PUSH_KEY_TO_PARENT,
00076                                 SET_BRANCH_KEY,
00077                         } action; // 0=none, 1=replace key1 with key2
00078                 };
00079 
00080                 BPlusTree();
00081                 ~BPlusTree();
00082                 void SetPoolPageSize(int size); // Set the page size for the memory pool.  Optionsl
00083                 bool Get(const KeyType key, DataType &out) const;
00084                 bool Delete(const KeyType key);
00085                 bool Delete(const KeyType key, DataType &out);
00086                 bool Insert(const KeyType key, const DataType &data);
00087                 void Clear(void);
00088                 unsigned Size(void) const;
00089                 bool IsEmpty(void) const;
00090                 Page<KeyType, DataType, order> *GetListHead(void) const;
00091                 DataType GetDataHead(void) const;
00092                 void PrintLeaves(void);
00093                 void ForEachLeaf(void (*func)(Page<KeyType, DataType, order> * leaf, int index));
00094                 void ForEachData(void (*func)(DataType input, int index));
00095                 void PrintGraph(void);
00096         protected:
00097                 void ValidateTreeRecursive(Page<KeyType, DataType, order> *cur);
00098                 void DeleteFromPageAtIndex(const int index, Page<KeyType, DataType, order> *cur);
00099                 static void PrintLeaf(Page<KeyType, DataType, order> * leaf, int index);
00100                 void FreePages(void);
00101                 bool GetIndexOf(const KeyType key, Page<KeyType, DataType, order> *page, int *out) const;
00102                 void ShiftKeysLeft(Page<KeyType, DataType, order> *cur);
00103                 bool CanRotateLeft(Page<KeyType, DataType, order> *cur, int childIndex);
00104                 bool CanRotateRight(Page<KeyType, DataType, order> *cur, int childIndex);
00105                 void RotateRight(Page<KeyType, DataType, order> *cur, int childIndex, ReturnAction *returnAction);
00106                 void RotateLeft(Page<KeyType, DataType, order> *cur, int childIndex, ReturnAction *returnAction);
00107                 Page<KeyType, DataType, order>* InsertIntoNode(const KeyType key, const DataType &childData, int insertionIndex, Page<KeyType, DataType, order> *nodeData, Page<KeyType, DataType, order> *cur, ReturnAction* returnAction);
00108                 Page<KeyType, DataType, order>* InsertBranchDown(const KeyType key, const DataType &data,Page<KeyType, DataType, order> *cur, ReturnAction* returnAction, bool *success);
00109                 Page<KeyType, DataType, order>* GetLeafFromKey(const KeyType key) const;
00110                 bool FindDeleteRebalance(const KeyType key, Page<KeyType, DataType, order> *cur, bool *underflow, KeyType rightRootKey, ReturnAction *returnAction, DataType &out);
00111                 bool FixUnderflow(int branchIndex, Page<KeyType, DataType, order> *cur, KeyType rightRootKey, ReturnAction *returnAction);
00112                 void ShiftNodeLeft(Page<KeyType, DataType, order> *cur);
00113                 void ShiftNodeRight(Page<KeyType, DataType, order> *cur);
00114 
00115                 MemoryPool<Page<KeyType, DataType, order> > pagePool;
00116                 Page<KeyType, DataType, order> *root, *leftmostLeaf;
00117         };
00118 
00119         template<class KeyType, class DataType, int order>
00120                 BPlusTree<KeyType, DataType, order>::BPlusTree ()
00121         {
00122                 RakAssert(order>1);
00123                 root=0;
00124                 leftmostLeaf=0;
00125         }
00126         template<class KeyType, class DataType, int order>
00127                 BPlusTree<KeyType, DataType, order>::~BPlusTree ()
00128         {
00129                 Clear();
00130         }
00131         template<class KeyType, class DataType, int order>
00132         void BPlusTree<KeyType, DataType, order>::SetPoolPageSize(int size)
00133         {
00134                 pagePool.SetPageSize(size);
00135         }
00136         template<class KeyType, class DataType, int order>
00137         bool BPlusTree<KeyType, DataType, order>::Get(const KeyType key, DataType &out) const
00138         {
00139                 if (root==0)
00140                         return false;
00141 
00142                 Page<KeyType, DataType, order>* leaf = GetLeafFromKey(key);
00143                 int childIndex;
00144                 
00145                 if (GetIndexOf(key, leaf, &childIndex))
00146                 {
00147                         out=leaf->data[childIndex];
00148                         return true;
00149                 }
00150                 return false;
00151         }
00152         template<class KeyType, class DataType, int order>
00153         void BPlusTree<KeyType, DataType, order>::DeleteFromPageAtIndex(const int index, Page<KeyType, DataType, order> *cur)
00154         {
00155                 int i;
00156                 for (i=index; i < cur->size-1; i++)
00157                         cur->keys[i]=cur->keys[i+1];
00158                 if (cur->isLeaf)
00159                 {
00160                         for (i=index; i < cur->size-1; i++)
00161                                 cur->data[i]=cur->data[i+1];
00162                 }
00163                 else
00164                 {
00165                         for (i=index; i < cur->size-1; i++)
00166                                 cur->children[i+1]=cur->children[i+2];
00167                 }
00168                 cur->size--;
00169         }
00170         template<class KeyType, class DataType, int order>
00171         bool BPlusTree<KeyType, DataType, order>::Delete(const KeyType key)
00172         {
00173                 DataType temp;
00174                 return Delete(key, temp);
00175         }
00176         template<class KeyType, class DataType, int order>
00177         bool BPlusTree<KeyType, DataType, order>::Delete(const KeyType key, DataType &out)
00178         {
00179                 if (root==0)
00180                         return false;
00181 
00182                 ReturnAction returnAction;
00183                 returnAction.action=ReturnAction::NO_ACTION;
00184                 int childIndex;
00185                 bool underflow=false;
00186                 if (root==leftmostLeaf)
00187                 {
00188                         if (GetIndexOf(key, root, &childIndex)==false)
00189                                 return false;
00190                         out=root->data[childIndex];
00191                         DeleteFromPageAtIndex(childIndex,root);
00192                         if (root->size==0)
00193                         {
00194                                 pagePool.Release(root, __FILE__,__LINE__);
00195                                 root=0;
00196                                 leftmostLeaf=0;
00197                         }
00198                         return true;
00199                 }
00200                 else if (FindDeleteRebalance(key, root, &underflow,root->keys[0], &returnAction, out)==false)
00201                         return false;
00202 
00203 //              RakAssert(returnAction.action==ReturnAction::NO_ACTION);
00204 
00205                 if (underflow && root->size==0)
00206                 {
00207                         // Move the root down.
00208                         Page<KeyType, DataType, order> *oldRoot=root;
00209                         root=root->children[0];
00210                         pagePool.Release(oldRoot, __FILE__,__LINE__);
00211                         // memset(oldRoot,0,sizeof(root));
00212                 }               
00213         
00214                 return true;
00215         }
00216         template<class KeyType, class DataType, int order>
00217         bool BPlusTree<KeyType, DataType, order>::FindDeleteRebalance(const KeyType key, Page<KeyType, DataType, order> *cur, bool *underflow, KeyType rightRootKey, ReturnAction *returnAction, DataType &out)
00218         {
00219                 // Get index of child to follow.
00220                 int branchIndex, childIndex;
00221                 if (GetIndexOf(key, cur, &childIndex))
00222                         branchIndex=childIndex+1;
00223                 else
00224                         branchIndex=childIndex;
00225 
00226                 // If child is not a leaf, call recursively
00227                 if (cur->children[branchIndex]->isLeaf==false)
00228                 {
00229                         if (branchIndex<cur->size)
00230                                 rightRootKey=cur->keys[branchIndex]; // Shift right to left
00231                         else
00232                                 rightRootKey=cur->keys[branchIndex-1]; // Shift center to left
00233 
00234                         if (FindDeleteRebalance(key, cur->children[branchIndex], underflow, rightRootKey, returnAction, out)==false)
00235                                 return false;
00236 
00237                         // Call again in case the root key changed
00238                         if (branchIndex<cur->size)
00239                                 rightRootKey=cur->keys[branchIndex]; // Shift right to left
00240                         else
00241                                 rightRootKey=cur->keys[branchIndex-1]; // Shift center to left
00242 
00243                         if (returnAction->action==ReturnAction::SET_BRANCH_KEY && branchIndex!=childIndex)
00244                         {
00245                                 returnAction->action=ReturnAction::NO_ACTION;
00246                                 cur->keys[childIndex]=returnAction->key1;
00247 
00248                                 if (branchIndex<cur->size)
00249                                         rightRootKey=cur->keys[branchIndex]; // Shift right to left
00250                                 else
00251                                         rightRootKey=cur->keys[branchIndex-1]; // Shift center to left
00252                         }
00253                 }
00254                 else
00255                 {
00256                         // If child is a leaf, get the index of the key.  If the item is not found, cancel delete.
00257                         if (GetIndexOf(key, cur->children[branchIndex], &childIndex)==false)
00258                                 return false;
00259 
00260                         // Delete:
00261                         // Remove childIndex from the child at branchIndex
00262                         out=cur->children[branchIndex]->data[childIndex];
00263                         DeleteFromPageAtIndex(childIndex, cur->children[branchIndex]);
00264 
00265                         if (childIndex==0)
00266                         {
00267                                 if (branchIndex>0)
00268                                         cur->keys[branchIndex-1]=cur->children[branchIndex]->keys[0];
00269 
00270                                 if (branchIndex==0)
00271                                 {
00272                                         returnAction->action=ReturnAction::SET_BRANCH_KEY;
00273                                         returnAction->key1=cur->children[0]->keys[0];
00274                                 }                               
00275                         }
00276 
00277                         if (cur->children[branchIndex]->size < order/2)
00278                                 *underflow=true;
00279                         else
00280                                 *underflow=false;
00281                 }
00282 
00283                 // Fix underflow:
00284                 if (*underflow)
00285                 {
00286                         *underflow=FixUnderflow(branchIndex, cur, rightRootKey, returnAction);
00287                 }
00288 
00289                 return true;
00290         }
00291         template<class KeyType, class DataType, int order>
00292         bool BPlusTree<KeyType, DataType, order>::FixUnderflow(int branchIndex, Page<KeyType, DataType, order> *cur, KeyType rightRootKey, ReturnAction *returnAction)
00293         {
00294                 // Borrow from a neighbor that has excess.
00295                 Page<KeyType, DataType, order> *source;
00296                 Page<KeyType, DataType, order> *dest;
00297 
00298                 if (branchIndex>0 && cur->children[branchIndex-1]->size > order/2)
00299                 {
00300                         dest=cur->children[branchIndex];
00301                         source=cur->children[branchIndex-1];
00302 
00303                         // Left has excess
00304                         ShiftNodeRight(dest);
00305                         if (dest->isLeaf)
00306                         {
00307                                 dest->keys[0]=source->keys[source->size-1];
00308                                 dest->data[0]=source->data[source->size-1];
00309                         }
00310                         else
00311                         {
00312                                 dest->children[0]=source->children[source->size];
00313                                 dest->keys[0]=cur->keys[branchIndex-1];
00314                         }
00315                         // Update the parent key for the child (middle)
00316                         cur->keys[branchIndex-1]=source->keys[source->size-1];
00317                         source->size--;
00318 
00319         //              if (branchIndex==0)
00320         //              {
00321         //                      returnAction->action=ReturnAction::SET_BRANCH_KEY;
00322         //                      returnAction->key1=dest->keys[0];
00323         //              }
00324 
00325                         // No underflow
00326                         return false;
00327                 }
00328                 else if (branchIndex<cur->size && cur->children[branchIndex+1]->size > order/2)
00329                 {
00330                         dest=cur->children[branchIndex];
00331                         source=cur->children[branchIndex+1];
00332 
00333                         // Right has excess
00334                         if (dest->isLeaf)
00335                         {
00336                                 dest->keys[dest->size]=source->keys[0];
00337                                 dest->data[dest->size]=source->data[0];
00338 
00339                                 // The first key in the leaf after shifting is the parent key for the right branch
00340                                 cur->keys[branchIndex]=source->keys[1];
00341 
00342 #ifdef _MSC_VER
00343 #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
00344 #endif
00345                                 if (order<=3 && dest->size==0)
00346                                 {
00347                                         if (branchIndex==0)
00348                                         {
00349                                                 returnAction->action=ReturnAction::SET_BRANCH_KEY;
00350                                                 returnAction->key1=dest->keys[0];
00351                                         }
00352                                         else
00353                                                 cur->keys[branchIndex-1]=cur->children[branchIndex]->keys[0];
00354                                 }
00355                         }
00356                         else
00357                         {
00358                                 if (returnAction->action==ReturnAction::NO_ACTION)
00359                                 {
00360                                         returnAction->action=ReturnAction::SET_BRANCH_KEY;
00361                                         returnAction->key1=dest->keys[0];
00362                                 }
00363                                 
00364                                 dest->keys[dest->size]=rightRootKey;
00365                                 dest->children[dest->size+1]=source->children[0];
00366 
00367                                 // The shifted off key is the leftmost key for a node
00368                                 cur->keys[branchIndex]=source->keys[0];
00369                         }
00370 
00371 
00372                         dest->size++;
00373                         ShiftNodeLeft(source);
00374 
00375                         //cur->keys[branchIndex]=source->keys[0];
00376 
00377 //                      returnAction->action=ReturnAction::SET_BRANCH_KEY;
00378 //                      returnAction->key1=dest->keys[dest->size-1];
00379 
00380                         // No underflow
00381                         return false;
00382                 }
00383                 else
00384                 {
00385                         int sourceIndex;
00386 
00387                         // If no neighbors have excess, merge two branches.
00388                         //
00389                         // To merge two leaves, just copy the data and keys over.
00390                         //
00391                         // To merge two branches, copy the pointers and keys over, using rightRootKey as the key for the extra pointer
00392                         if (branchIndex<cur->size)
00393                         {
00394                                 // Merge right child to current child and delete right child.
00395                                 dest=cur->children[branchIndex];
00396                                 source=cur->children[branchIndex+1];
00397                         }
00398                         else
00399                         {
00400                                 // Move current child to left and delete current child
00401                                 dest=cur->children[branchIndex-1];
00402                                 source=cur->children[branchIndex];
00403                         }
00404 
00405                         // Merge
00406                         if (dest->isLeaf)
00407                         {
00408                                 for (sourceIndex=0; sourceIndex<source->size; sourceIndex++)
00409                                 {
00410                                         dest->keys[dest->size]=source->keys[sourceIndex];
00411                                         dest->data[dest->size++]=source->data[sourceIndex];
00412                                 }
00413                         }
00414                         else
00415                         {
00416                                 // We want the tree root key of the source, not the current.
00417                                 dest->keys[dest->size]=rightRootKey;
00418                                 dest->children[dest->size++ + 1]=source->children[0];
00419                                 for (sourceIndex=0; sourceIndex<source->size; sourceIndex++)
00420                                 {
00421                                         dest->keys[dest->size]=source->keys[sourceIndex];
00422                                         dest->children[dest->size++ + 1]=source->children[sourceIndex + 1];
00423                                 }
00424                         }
00425 
00426 #ifdef _MSC_VER
00427 #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
00428 #endif
00429                         if (order<=3 && branchIndex>0 && cur->children[branchIndex]->isLeaf) // With order==2 it is possible to delete data[0], which is not possible with higher orders.
00430                                 cur->keys[branchIndex-1]=cur->children[branchIndex]->keys[0];
00431 
00432                         if (branchIndex<cur->size)
00433                         {
00434                                 // Update the parent key, removing the source (right)
00435                                 DeleteFromPageAtIndex(branchIndex, cur);
00436                         }
00437                         else
00438                         {
00439                                 if (branchIndex>0)
00440                                 {
00441                                         // Update parent key, removing the source (current)
00442                                         DeleteFromPageAtIndex(branchIndex-1, cur);
00443                                 }
00444                         }
00445 
00446                         if (branchIndex==0 && dest->isLeaf)
00447                         {
00448                                 returnAction->action=ReturnAction::SET_BRANCH_KEY;
00449                                 returnAction->key1=dest->keys[0];
00450                         }
00451 
00452                         if (source==leftmostLeaf)
00453                                 leftmostLeaf=source->next;
00454 
00455                         if (source->isLeaf)
00456                         {
00457                                 if (source->previous)
00458                                         source->previous->next=source->next;
00459                                 if (source->next)
00460                                         source->next->previous=source->previous;
00461                         }                       
00462 
00463                         // Free the source node
00464                         pagePool.Release(source, __FILE__,__LINE__);
00465                         // memset(source,0,sizeof(root));
00466 
00467                         // Return underflow or not of parent.
00468                         return cur->size < order/2;
00469                 }
00470         }
00471         template<class KeyType, class DataType, int order>
00472                 void BPlusTree<KeyType, DataType, order>::ShiftNodeRight(Page<KeyType, DataType, order> *cur)
00473         {
00474                 int i;
00475                 for (i=cur->size; i>0; i--)
00476                         cur->keys[i]=cur->keys[i-1];
00477                 if (cur->isLeaf)
00478                 {
00479                         for (i=cur->size; i>0; i--)
00480                                 cur->data[i]=cur->data[i-1];
00481                 }
00482                 else
00483                 {
00484                         for (i=cur->size+1; i>0; i--)
00485                                 cur->children[i]=cur->children[i-1];
00486                 }
00487 
00488                 cur->size++;
00489         }
00490         template<class KeyType, class DataType, int order>
00491                 void BPlusTree<KeyType, DataType, order>::ShiftNodeLeft(Page<KeyType, DataType, order> *cur)
00492         {
00493                 int i;
00494                 for (i=0; i < cur->size-1; i++)
00495                         cur->keys[i]=cur->keys[i+1];
00496                 if (cur->isLeaf)
00497                 {
00498                         for (i=0; i < cur->size; i++)
00499                                 cur->data[i]=cur->data[i+1];
00500                 }
00501                 else
00502                 {
00503                         for (i=0; i < cur->size; i++)
00504                                 cur->children[i]=cur->children[i+1];
00505                 }
00506                 cur->size--;
00507         }
00508         template<class KeyType, class DataType, int order>
00509         Page<KeyType, DataType, order>* BPlusTree<KeyType, DataType, order>::InsertIntoNode(const KeyType key, const DataType &leafData, int insertionIndex, Page<KeyType, DataType, order> *nodeData, Page<KeyType, DataType, order> *cur, ReturnAction* returnAction)
00510         {
00511                 int i;
00512                 if (cur->size < order)
00513                 {
00514                         for (i=cur->size; i > insertionIndex; i--)
00515                                 cur->keys[i]=cur->keys[i-1];
00516                         if (cur->isLeaf)
00517                         {
00518                                 for (i=cur->size; i > insertionIndex; i--)
00519                                         cur->data[i]=cur->data[i-1];
00520                         }
00521                         else
00522                         {
00523                                 for (i=cur->size+1; i > insertionIndex+1; i--)
00524                                         cur->children[i]=cur->children[i-1];
00525                         }
00526                         cur->keys[insertionIndex]=key;
00527                         if (cur->isLeaf)
00528                                 cur->data[insertionIndex]=leafData;
00529                         else
00530                                 cur->children[insertionIndex+1]=nodeData;
00531 
00532                         cur->size++;
00533                 }
00534                 else
00535                 {
00536                         Page<KeyType, DataType, order>* newPage = pagePool.Allocate( __FILE__, __LINE__ );
00537                         newPage->isLeaf=cur->isLeaf;
00538                         if (cur->isLeaf)
00539                         {
00540                                 newPage->next=cur->next;
00541                                 if (cur->next)
00542                                         cur->next->previous=newPage;
00543                                 newPage->previous=cur;
00544                                 cur->next=newPage;
00545                         }
00546 
00547                         int destIndex, sourceIndex;
00548 
00549                         if (insertionIndex>=(order+1)/2)
00550                         {
00551                                 destIndex=0;
00552                                 sourceIndex=order/2;
00553 
00554                                 for (; sourceIndex < insertionIndex; sourceIndex++, destIndex++)
00555                                 {
00556                                         newPage->keys[destIndex]=cur->keys[sourceIndex];
00557                                 }
00558                                 newPage->keys[destIndex++]=key;
00559                                 for (; sourceIndex < order; sourceIndex++, destIndex++)
00560                                 {
00561                                         newPage->keys[destIndex]=cur->keys[sourceIndex];
00562                                 }
00563 
00564                                 destIndex=0;
00565                                 sourceIndex=order/2;
00566                                 if (cur->isLeaf)
00567                                 {
00568                                         for (; sourceIndex < insertionIndex; sourceIndex++, destIndex++)
00569                                         {
00570                                                 newPage->data[destIndex]=cur->data[sourceIndex];
00571                                         }
00572                                         newPage->data[destIndex++]=leafData;
00573                                         for (; sourceIndex < order; sourceIndex++, destIndex++)
00574                                         {
00575                                                 newPage->data[destIndex]=cur->data[sourceIndex];
00576                                         }
00577                                 }
00578                                 else
00579                                 {
00580                                         
00581                                         for (; sourceIndex < insertionIndex; sourceIndex++, destIndex++)
00582                                         {
00583                                                 newPage->children[destIndex]=cur->children[sourceIndex+1];
00584                                         }
00585                                         newPage->children[destIndex++]=nodeData;
00586 
00587                                         // sourceIndex+1 is sort of a hack but it works - because there is one extra child than keys
00588                                         // skip past the last child for cur
00589                                         for (; sourceIndex+1 < cur->size+1; sourceIndex++, destIndex++)
00590                                         {
00591                                                 newPage->children[destIndex]=cur->children[sourceIndex+1];
00592                                         }
00593 
00594                                         // the first key is the middle key.  Remove it from the page and push it to the parent
00595                                         returnAction->action=ReturnAction::PUSH_KEY_TO_PARENT;
00596                                         returnAction->key1=newPage->keys[0];
00597                                         for (int i=0; i < destIndex-1; i++)
00598                                                 newPage->keys[i]=newPage->keys[i+1];
00599                                         
00600                                 }
00601                                 cur->size=order/2;
00602                         }
00603                         else
00604                         {
00605                                 destIndex=0;
00606                                 sourceIndex=(order+1)/2-1;
00607                                 for (; sourceIndex < order; sourceIndex++, destIndex++)
00608                                         newPage->keys[destIndex]=cur->keys[sourceIndex];
00609                                 destIndex=0;
00610                                 if (cur->isLeaf)
00611                                 {
00612                                         sourceIndex=(order+1)/2-1;
00613                                         for (; sourceIndex < order; sourceIndex++, destIndex++)
00614                                                 newPage->data[destIndex]=cur->data[sourceIndex];
00615                                 }
00616                                 else
00617                                 {
00618                                         sourceIndex=(order+1)/2;
00619                                         for (; sourceIndex < order+1; sourceIndex++, destIndex++)
00620                                                 newPage->children[destIndex]=cur->children[sourceIndex];
00621 
00622                                         // the first key is the middle key.  Remove it from the page and push it to the parent
00623                                         returnAction->action=ReturnAction::PUSH_KEY_TO_PARENT;
00624                                         returnAction->key1=newPage->keys[0];
00625                                         for (int i=0; i < destIndex-1; i++)
00626                                                 newPage->keys[i]=newPage->keys[i+1];
00627                                 }
00628                                 cur->size=(order+1)/2-1;
00629                                 if (cur->size)
00630                                 {
00631                                         bool b = GetIndexOf(key, cur, &insertionIndex);
00632                                         (void) b;
00633                                         RakAssert(b==false);
00634                                 }
00635                                 else
00636                                         insertionIndex=0;
00637                                 InsertIntoNode(key, leafData, insertionIndex, nodeData, cur, returnAction);
00638                         }
00639 
00640                         newPage->size=destIndex;
00641 
00642                         return newPage;
00643                 }
00644 
00645                 return 0;
00646         }
00647 
00648         template<class KeyType, class DataType, int order>
00649         bool BPlusTree<KeyType, DataType, order>::CanRotateLeft(Page<KeyType, DataType, order> *cur, int childIndex)
00650         {
00651                 return childIndex>0 && cur->children[childIndex-1]->size<order;
00652         }
00653 
00654         template<class KeyType, class DataType, int order>
00655         void BPlusTree<KeyType, DataType, order>::RotateLeft(Page<KeyType, DataType, order> *cur, int childIndex, ReturnAction *returnAction)
00656         {
00657                 Page<KeyType, DataType, order> *dest = cur->children[childIndex-1];
00658                 Page<KeyType, DataType, order> *source = cur->children[childIndex];
00659                 returnAction->key1=source->keys[0];
00660                 dest->keys[dest->size]=source->keys[0];
00661                 dest->data[dest->size]=source->data[0];
00662                 dest->size++;
00663                 for (int i=0; i < source->size-1; i++)
00664                 {
00665                         source->keys[i]=source->keys[i+1];
00666                         source->data[i]=source->data[i+1];
00667                 }
00668                 source->size--;
00669                 cur->keys[childIndex-1]=source->keys[0];
00670                 returnAction->key2=source->keys[0];
00671         }
00672 
00673         template<class KeyType, class DataType, int order>
00674         bool BPlusTree<KeyType, DataType, order>::CanRotateRight(Page<KeyType, DataType, order> *cur, int childIndex)
00675         {
00676                 return childIndex < cur->size && cur->children[childIndex+1]->size<order;
00677         }
00678 
00679         template<class KeyType, class DataType, int order>
00680         void BPlusTree<KeyType, DataType, order>::RotateRight(Page<KeyType, DataType, order> *cur, int childIndex, ReturnAction *returnAction)
00681         {
00682                 Page<KeyType, DataType, order> *dest = cur->children[childIndex+1];
00683                 Page<KeyType, DataType, order> *source = cur->children[childIndex];
00684                 returnAction->key1=dest->keys[0];
00685                 for (int i= dest->size; i > 0; i--)
00686                 {
00687                         dest->keys[i]=dest->keys[i-1];
00688                         dest->data[i]=dest->data[i-1];
00689                 }
00690                 dest->keys[0]=source->keys[source->size-1];
00691                 dest->data[0]=source->data[source->size-1];
00692                 dest->size++;
00693                 source->size--;
00694 
00695                 cur->keys[childIndex]=dest->keys[0];
00696                 returnAction->key2=dest->keys[0];
00697         }
00698         template<class KeyType, class DataType, int order>
00699                 Page<KeyType, DataType, order>* BPlusTree<KeyType, DataType, order>::GetLeafFromKey(const KeyType key) const
00700         {
00701                 Page<KeyType, DataType, order>* cur = root;
00702                 int childIndex;
00703                 while (cur->isLeaf==false)
00704                 {
00705                         // When searching, if we match the exact key we go down the pointer after that index
00706                         if (GetIndexOf(key, cur, &childIndex))
00707                                 childIndex++;
00708                         cur = cur->children[childIndex];
00709                 }
00710                 return cur;
00711         }
00712 
00713         template<class KeyType, class DataType, int order>
00714         Page<KeyType, DataType, order>* BPlusTree<KeyType, DataType, order>::InsertBranchDown(const KeyType key, const DataType &data,Page<KeyType, DataType, order> *cur, ReturnAction *returnAction, bool *success)
00715         {
00716                 int childIndex;
00717                 int branchIndex;
00718                 if (GetIndexOf(key, cur, &childIndex))
00719                         branchIndex=childIndex+1;
00720                 else
00721                         branchIndex=childIndex;
00722                 Page<KeyType, DataType, order>* newPage;
00723                 if (cur->isLeaf==false)
00724                 {
00725                         if (cur->children[branchIndex]->isLeaf==true && cur->children[branchIndex]->size==order)
00726                         {
00727                                 if (branchIndex==childIndex+1)
00728                                 {
00729                                         *success=false;
00730                                         return 0; // Already exists
00731                                 }
00732 
00733                                 if (CanRotateLeft(cur, branchIndex))
00734                                 {
00735                                         returnAction->action=ReturnAction::REPLACE_KEY1_WITH_KEY2;
00736                                         if (key > cur->children[branchIndex]->keys[0])
00737                                         {                                               
00738                                                 RotateLeft(cur, branchIndex, returnAction);
00739 
00740                                                 int insertionIndex;
00741                                                 GetIndexOf(key, cur->children[branchIndex], &insertionIndex);
00742                                                 InsertIntoNode(key, data, insertionIndex, 0, cur->children[branchIndex], 0);
00743                                         }
00744                                         else
00745                                         {
00746                                                 // Move head element to left and replace it with key,data
00747                                                 Page<KeyType, DataType, order>* dest=cur->children[branchIndex-1];
00748                                                 Page<KeyType, DataType, order>* source=cur->children[branchIndex];
00749                                                 returnAction->key1=source->keys[0];
00750                                                 returnAction->key2=key;
00751                                                 dest->keys[dest->size]=source->keys[0];
00752                                                 dest->data[dest->size]=source->data[0];
00753                                                 dest->size++;
00754                                                 source->keys[0]=key;
00755                                                 source->data[0]=data;   
00756                                         }
00757                                         cur->keys[branchIndex-1]=cur->children[branchIndex]->keys[0];
00758                                         
00759                                         return 0;
00760                                 }
00761                                 else if (CanRotateRight(cur, branchIndex))
00762                                 {
00763                                         returnAction->action=ReturnAction::REPLACE_KEY1_WITH_KEY2;
00764                                         
00765                                         if (key < cur->children[branchIndex]->keys[cur->children[branchIndex]->size-1])
00766                                         {
00767                                                 RotateRight(cur, branchIndex, returnAction);
00768 
00769                                                 int insertionIndex;
00770                                                 GetIndexOf(key, cur->children[branchIndex], &insertionIndex);
00771                                                 InsertIntoNode(key, data, insertionIndex, 0, cur->children[branchIndex], 0);
00772                                                 
00773                                         }
00774                                         else
00775                                         {
00776                                                 // Insert to the head of the right leaf instead and change our key
00777                                                 returnAction->key1=cur->children[branchIndex+1]->keys[0];
00778                                                 InsertIntoNode(key, data, 0, 0, cur->children[branchIndex+1], 0);                                               
00779                                                 returnAction->key2=key;
00780                                         }
00781                                         cur->keys[branchIndex]=cur->children[branchIndex+1]->keys[0];
00782                                         return 0;                                       
00783                                 }
00784                         }
00785 
00786                         newPage=InsertBranchDown(key,data,cur->children[branchIndex], returnAction, success);
00787                         if (returnAction->action==ReturnAction::REPLACE_KEY1_WITH_KEY2)
00788                         {
00789                                 if (branchIndex>0 && cur->keys[branchIndex-1]==returnAction->key1)
00790                                         cur->keys[branchIndex-1]=returnAction->key2;
00791                         }
00792                         if (newPage)
00793                         {
00794                                 if (newPage->isLeaf==false)
00795                                 {
00796                                         RakAssert(returnAction->action==ReturnAction::PUSH_KEY_TO_PARENT);
00797                                         newPage->size--; 
00798                                         return InsertIntoNode(returnAction->key1, data, branchIndex, newPage, cur, returnAction);
00799                                 }
00800                                 else
00801                                 {
00802                                         return InsertIntoNode(newPage->keys[0], data, branchIndex, newPage, cur, returnAction);
00803                                 }                               
00804                         }
00805                 }
00806                 else
00807                 {
00808                         if (branchIndex==childIndex+1)
00809                         {
00810                                 *success=false;
00811                                 return 0; // Already exists                             
00812                         }
00813                         else
00814                         {
00815                                 return InsertIntoNode(key, data, branchIndex, 0, cur, returnAction);
00816                         }
00817                 }
00818                 
00819                 return 0;
00820         }
00821         template<class KeyType, class DataType, int order>
00822                 bool BPlusTree<KeyType, DataType, order>::Insert(const KeyType key, const DataType &data)
00823         {
00824                 if (root==0)
00825                 {
00826                         // Allocate root and make root a leaf
00827                         root = pagePool.Allocate( __FILE__, __LINE__ );
00828                         root->isLeaf=true;
00829                         leftmostLeaf=root;
00830                         root->size=1;
00831                         root->keys[0]=key;
00832                         root->data[0]=data;
00833                         root->next=0;
00834                         root->previous=0;
00835                 }
00836                 else
00837                 {
00838                         bool success=true;
00839                         ReturnAction returnAction;
00840                         returnAction.action=ReturnAction::NO_ACTION;
00841                         Page<KeyType, DataType, order>* newPage = InsertBranchDown(key, data, root, &returnAction, &success);
00842                         if (success==false)
00843                                 return false;
00844                         if (newPage)
00845                         {
00846                                 KeyType newKey;
00847                                 if (newPage->isLeaf==false)
00848                                 {
00849                                         // One key is pushed up through the stack.  I store that at keys[0] but it has to be removed for the page to be correct
00850                                         RakAssert(returnAction.action==ReturnAction::PUSH_KEY_TO_PARENT);
00851                                         newKey=returnAction.key1;
00852                                         newPage->size--;
00853                                 }
00854                                 else
00855                                          newKey = newPage->keys[0];
00856                                 // propagate the root
00857                                 Page<KeyType, DataType, order>* newRoot = pagePool.Allocate( __FILE__, __LINE__ );
00858                                 newRoot->isLeaf=false;
00859                                 newRoot->size=1;
00860                                 newRoot->keys[0]=newKey;
00861                                 newRoot->children[0]=root;
00862                                 newRoot->children[1]=newPage;
00863                                 root=newRoot;
00864                         }
00865                 }
00866 
00867                 return true;
00868         }
00869         template<class KeyType, class DataType, int order>
00870         void BPlusTree<KeyType, DataType, order>::ShiftKeysLeft(Page<KeyType, DataType, order> *cur)
00871         {
00872                 int i;
00873                 for (i=0; i < cur->size; i++)
00874                         cur->keys[i]=cur->keys[i+1];
00875         }
00876         template<class KeyType, class DataType, int order>
00877                 void BPlusTree<KeyType, DataType, order>::Clear(void)
00878         {
00879                 if (root)
00880                 {
00881                         FreePages();
00882                         leftmostLeaf=0;
00883                         root=0;
00884                 }
00885                 pagePool.Clear(__FILE__, __LINE__);
00886         }
00887         template<class KeyType, class DataType, int order>
00888                 unsigned BPlusTree<KeyType, DataType, order>::Size(void) const
00889         {
00890                 int count=0;
00891                 DataStructures::Page<KeyType, DataType, order> *cur = GetListHead();
00892                 while (cur)
00893                 {
00894                         count+=cur->size;
00895                         cur=cur->next;
00896                 }
00897                 return count;
00898         }
00899         template<class KeyType, class DataType, int order>
00900                 bool BPlusTree<KeyType, DataType, order>::IsEmpty(void) const
00901         {
00902                 return root==0;
00903         }
00904         template<class KeyType, class DataType, int order>
00905                 bool BPlusTree<KeyType, DataType, order>::GetIndexOf(const KeyType key, Page<KeyType, DataType, order> *page, int *out) const
00906         {
00907                 RakAssert(page->size>0);
00908                 int index, upperBound, lowerBound;
00909                 upperBound=page->size-1;
00910                 lowerBound=0;
00911                 index = page->size/2;
00912 
00913 #ifdef _MSC_VER
00914 #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
00915 #endif
00916                 while (1)
00917                 {
00918                         if (key==page->keys[index])
00919                         {
00920                                 *out=index;
00921                                 return true;
00922                         }
00923                         else if (key<page->keys[index])
00924                                 upperBound=index-1;
00925                         else
00926                                 lowerBound=index+1;
00927 
00928                         index=lowerBound+(upperBound-lowerBound)/2;
00929 
00930                         if (lowerBound>upperBound)
00931                         {
00932                                 *out=lowerBound;
00933                                 return false; // No match
00934                         }
00935                 }
00936         }
00937         template<class KeyType, class DataType, int order>
00938                 void BPlusTree<KeyType, DataType, order>::FreePages(void)
00939         {
00940                 DataStructures::Queue<DataStructures::Page<KeyType, DataType, order> *> queue;
00941                 DataStructures::Page<KeyType, DataType, order> *ptr;
00942                 int i;
00943                 queue.Push(root, __FILE__, __LINE__ );
00944                 while (queue.Size())
00945                 {
00946                         ptr=queue.Pop();
00947                         if (ptr->isLeaf==false)
00948                         {
00949                                 for (i=0; i < ptr->size+1; i++)
00950                                         queue.Push(ptr->children[i], __FILE__, __LINE__ );
00951                         }                       
00952                         pagePool.Release(ptr, __FILE__,__LINE__);
00953                 //      memset(ptr,0,sizeof(root));
00954                 };
00955         }
00956         template<class KeyType, class DataType, int order>
00957                 Page<KeyType, DataType, order> *BPlusTree<KeyType, DataType, order>::GetListHead(void) const
00958         {
00959                 return leftmostLeaf;
00960         }
00961         template<class KeyType, class DataType, int order>
00962         DataType BPlusTree<KeyType, DataType, order>::GetDataHead(void) const
00963         {
00964                 return leftmostLeaf->data[0];
00965         }
00966         template<class KeyType, class DataType, int order>
00967                 void BPlusTree<KeyType, DataType, order>::ForEachLeaf(void (*func)(Page<KeyType, DataType, order> * leaf, int index))
00968         {
00969                 int count=0;
00970                 DataStructures::Page<KeyType, DataType, order> *cur = GetListHead();
00971                 while (cur)
00972                 {
00973                         func(cur, count++);
00974                         cur=cur->next;
00975                 }
00976         }
00977         template<class KeyType, class DataType, int order>
00978                 void BPlusTree<KeyType, DataType, order>::ForEachData(void (*func)(DataType input, int index))
00979         {
00980                 int count=0,i;
00981                 DataStructures::Page<KeyType, DataType, order> *cur = GetListHead();
00982                 while (cur)
00983                 {
00984                         for (i=0; i < cur->size; i++)
00985                                 func(cur->data[i], count++);
00986                         cur=cur->next;
00987                 }
00988         }
00989         template<class KeyType, class DataType, int order>
00990                 void BPlusTree<KeyType, DataType, order>::PrintLeaf(Page<KeyType, DataType, order> * leaf, int index)
00991         {
00992                 int i;
00993                 RAKNET_DEBUG_PRINTF("%i] SELF=%p\n", index+1, leaf);
00994                 for (i=0; i < leaf->size; i++)
00995                         RAKNET_DEBUG_PRINTF(" %i. %i\n", i+1, leaf->data[i]);
00996         }
00997         template<class KeyType, class DataType, int order>
00998                 void BPlusTree<KeyType, DataType, order>::PrintLeaves(void)
00999         {
01000                 ForEachLeaf(PrintLeaf);
01001         }
01002 
01003         template<class KeyType, class DataType, int order>
01004         void BPlusTree<KeyType, DataType, order>::ValidateTreeRecursive(Page<KeyType, DataType, order> *cur)
01005         {
01006                 RakAssert(cur==root || cur->size>=order/2);
01007 
01008                 if (cur->children[0]->isLeaf)
01009                 {
01010                         RakAssert(cur->children[0]->keys[0] < cur->keys[0]);
01011                         for (int i=0; i < cur->size; i++)
01012                         {
01013                                 RakAssert(cur->children[i+1]->keys[0]==cur->keys[i]);
01014                         }
01015                 }
01016                 else
01017                 {
01018                         for (int i=0; i < cur->size+1; i++)
01019                                 ValidateTreeRecursive(cur->children[i]);
01020                 }
01021         }
01022 
01023         template<class KeyType, class DataType, int order>
01024         void BPlusTree<KeyType, DataType, order>::PrintGraph(void)
01025         {
01026                 DataStructures::Queue<DataStructures::Page<KeyType, DataType, order> *> queue;
01027                 queue.Push(root,__FILE__,__LINE__);
01028                 queue.Push(0,__FILE__,__LINE__);
01029                 DataStructures::Page<KeyType, DataType, order> *ptr;
01030                 int i,j;
01031                 if (root)
01032                 {
01033                         RAKNET_DEBUG_PRINTF("%p(", root);
01034                         for (i=0; i < root->size; i++)
01035                         {
01036                                 RAKNET_DEBUG_PRINTF("%i ", root->keys[i]);
01037                         }
01038                         RAKNET_DEBUG_PRINTF(") ");
01039                         RAKNET_DEBUG_PRINTF("\n");
01040                 }
01041                 while (queue.Size())
01042                 {
01043                         ptr=queue.Pop();
01044                         if (ptr==0)
01045                                 RAKNET_DEBUG_PRINTF("\n");
01046                         else if (ptr->isLeaf==false)
01047                         {
01048                                 for (i=0; i < ptr->size+1; i++)
01049                                 {
01050                                         RAKNET_DEBUG_PRINTF("%p(", ptr->children[i]);
01051                                         //RAKNET_DEBUG_PRINTF("(", ptr->children[i]);
01052                                         for (j=0; j < ptr->children[i]->size; j++)
01053                                                 RAKNET_DEBUG_PRINTF("%i ", ptr->children[i]->keys[j]);
01054                                         RAKNET_DEBUG_PRINTF(") ");
01055                                         queue.Push(ptr->children[i],__FILE__,__LINE__);
01056                                 }
01057                                 queue.Push(0,__FILE__,__LINE__);
01058                                 RAKNET_DEBUG_PRINTF(" -- ");
01059                         }
01060                 }
01061                 RAKNET_DEBUG_PRINTF("\n");
01062         }
01063 }
01064 #ifdef _MSC_VER
01065 #pragma warning( pop )
01066 #endif
01067 
01068 #endif
01069 
01070 // Code to test this hellish data structure.
01071 /*
01072 #include "DS_BPlusTree.h"
01073 #include <stdio.h>
01074 
01075 // Handle underflow on root.  If there is only one item left then I can go downwards.
01076 // Make sure I keep the leftmost pointer valid by traversing it
01077 // When I free a leaf, be sure to adjust the pointers around it.
01078 
01079 #include "Rand.h"
01080 
01081 void main(void)
01082 {
01083         DataStructures::BPlusTree<int, int, 16> btree;
01084         DataStructures::List<int> haveList, removedList;
01085         int temp;
01086         int i, j, index;
01087         int testSize;
01088         bool b;
01089 
01090         for (testSize=0; testSize < 514; testSize++)
01091         {
01092                 RAKNET_DEBUG_PRINTF("TestSize=%i\n", testSize);
01093 
01094                 for (i=0; i < testSize; i++)
01095                         haveList.Insert(i);
01096 
01097                 for (i=0; i < testSize; i++)
01098                 {
01099                         index=i+randomMT()%(testSize-i);
01100                         temp=haveList[index];
01101                         haveList[index]=haveList[i];
01102                         haveList[i]=temp;
01103                 }
01104 
01105                 for (i=0; i<testSize; i++)
01106                 {
01107                         btree.Insert(haveList[i], haveList[i]);
01108                         btree.ValidateTree();
01109                 }
01110 
01111                 for (i=0; i < testSize; i++)
01112                 {
01113                         index=i+randomMT()%(testSize-i);
01114                         temp=haveList[index];
01115                         haveList[index]=haveList[i];
01116                         haveList[i]=temp;
01117                 }
01118                 for (i=0; i<testSize; i++)
01119                 {
01120                         btree.Delete(haveList[0]); // Asserts on 8th call.  Fails on going to remove 8 (7th call)
01121                         removedList.Insert(haveList[0]);
01122                         haveList.RemoveAtIndex(0);
01123                         for (j=0; j < removedList.Size(); j++)
01124                         {
01125                                 b=btree.Get(removedList[j], temp);
01126                                 RakAssert(b==false);
01127                         }
01128                         for (j=0; j < haveList.Size(); j++)
01129                         {
01130                                 b=btree.Get(haveList[j], temp);
01131                                 RakAssert(b==true);
01132                                 RakAssert(haveList[j]==temp);
01133                         }
01134                         RakAssert(btree.Size()==haveList.Size());
01135                         btree.ValidateTree();
01136                 }
01137                 btree.Clear(__FILE__, __LINE__);
01138                 removedList.Clear(__FILE__, __LINE__);
01139                 haveList.Clear(__FILE__, __LINE__);
01140         }
01141 
01142         RAKNET_DEBUG_PRINTF("Done. %i\n", btree.Size());
01143         char ch[256];
01144         fgets(ch, sizeof(ch), stdin);
01145 }
01146 */

Generated on Thu Sep 30 2010 01:27:22 for RakNet by  doxygen 1.7.1