Shadowrun: Awakened 29 September 2011 - Build 871
Classes | Public Member Functions | Protected Member Functions | Static Protected Member Functions | Protected Attributes
DataStructures::BPlusTree< KeyType, DataType, order > Class Template Reference

#include <DS_BPlusTree.h>

Inheritance diagram for DataStructures::BPlusTree< KeyType, DataType, order >:

List of all members.

Classes

struct  ReturnAction

Public Member Functions

 BPlusTree ()
void Clear (void)
bool Delete (const KeyType key)
bool Delete (const KeyType key, DataType &out)
void ForEachData (void(*func)(DataType input, int index))
void ForEachLeaf (void(*func)(Page< KeyType, DataType, order > *leaf, int index))
bool Get (const KeyType key, DataType &out) const
DataType GetDataHead (void) const
Page< KeyType, DataType, order > * GetListHead (void) const
bool Insert (const KeyType key, const DataType &data)
bool IsEmpty (void) const
void PrintGraph (void)
void PrintLeaves (void)
void SetPoolPageSize (int size)
unsigned Size (void) const
 ~BPlusTree ()

Protected Member Functions

bool CanRotateLeft (Page< KeyType, DataType, order > *cur, int childIndex)
bool CanRotateRight (Page< KeyType, DataType, order > *cur, int childIndex)
void DeleteFromPageAtIndex (const int index, Page< KeyType, DataType, order > *cur)
bool FindDeleteRebalance (const KeyType key, Page< KeyType, DataType, order > *cur, bool *underflow, KeyType rightRootKey, ReturnAction *returnAction, DataType &out)
bool FixUnderflow (int branchIndex, Page< KeyType, DataType, order > *cur, KeyType rightRootKey, ReturnAction *returnAction)
void FreePages (void)
bool GetIndexOf (const KeyType key, Page< KeyType, DataType, order > *page, int *out) const
Page< KeyType, DataType, order > * GetLeafFromKey (const KeyType key) const
Page< KeyType, DataType, order > * InsertBranchDown (const KeyType key, const DataType &data, Page< KeyType, DataType, order > *cur, ReturnAction *returnAction, bool *success)
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)
void RotateLeft (Page< KeyType, DataType, order > *cur, int childIndex, ReturnAction *returnAction)
void RotateRight (Page< KeyType, DataType, order > *cur, int childIndex, ReturnAction *returnAction)
void ShiftKeysLeft (Page< KeyType, DataType, order > *cur)
void ShiftNodeLeft (Page< KeyType, DataType, order > *cur)
void ShiftNodeRight (Page< KeyType, DataType, order > *cur)
void ValidateTreeRecursive (Page< KeyType, DataType, order > *cur)

Static Protected Member Functions

static void PrintLeaf (Page< KeyType, DataType, order > *leaf, int index)

Protected Attributes

Page< KeyType, DataType, order > * leftmostLeaf
MemoryPool< Page< KeyType,
DataType, order > > 
pagePool
Page< KeyType, DataType, order > * root

Detailed Description

template<class KeyType, class DataType, int order>
class DataStructures::BPlusTree< KeyType, DataType, order >

A BPlus tree Written with efficiency and speed in mind.

Definition at line 64 of file DS_BPlusTree.h.


Constructor & Destructor Documentation

template<class KeyType , class DataType , int order>
DataStructures::BPlusTree< KeyType, DataType, order >::BPlusTree ( )

Definition at line 120 of file DS_BPlusTree.h.

References RakAssert.

    {
        RakAssert(order>1);
        root=0;
        leftmostLeaf=0;
    }
template<class KeyType , class DataType , int order>
DataStructures::BPlusTree< KeyType, DataType, order >::~BPlusTree ( )

Definition at line 127 of file DS_BPlusTree.h.

    {
        Clear();
    }

Member Function Documentation

template<class KeyType, class DataType, int order>
bool DataStructures::BPlusTree< KeyType, DataType, order >::CanRotateLeft ( Page< KeyType, DataType, order > *  cur,
int  childIndex 
) [protected]

Definition at line 649 of file DS_BPlusTree.h.

References DataStructures::Page< KeyType, DataType, order >::children, and DataStructures::Page< KeyType, DataType, order >::size.

    {
        return childIndex>0 && cur->children[childIndex-1]->size<order;
    }
template<class KeyType, class DataType, int order>
bool DataStructures::BPlusTree< KeyType, DataType, order >::CanRotateRight ( Page< KeyType, DataType, order > *  cur,
int  childIndex 
) [protected]

Definition at line 674 of file DS_BPlusTree.h.

References DataStructures::Page< KeyType, DataType, order >::children, and DataStructures::Page< KeyType, DataType, order >::size.

    {
        return childIndex < cur->size && cur->children[childIndex+1]->size<order;
    }
template<class KeyType , class DataType , int order>
void DataStructures::BPlusTree< KeyType, DataType, order >::Clear ( void  )

Definition at line 877 of file DS_BPlusTree.h.

References _FILE_AND_LINE_.

    {
        if (root)
        {
            FreePages();
            leftmostLeaf=0;
            root=0;
        }
        pagePool.Clear(_FILE_AND_LINE_);
    }
template<class KeyType, class DataType, int order>
bool DataStructures::BPlusTree< KeyType, DataType, order >::Delete ( const KeyType  key,
DataType &  out 
)

Definition at line 177 of file DS_BPlusTree.h.

References _FILE_AND_LINE_, DataStructures::BPlusTree< KeyType, DataType, order >::ReturnAction::action, and DataStructures::Page< KeyType, DataType, order >::children.

    {
        if (root==0)
            return false;

        ReturnAction returnAction;
        returnAction.action=ReturnAction::NO_ACTION;
        int childIndex;
        bool underflow=false;
        if (root==leftmostLeaf)
        {
            if (GetIndexOf(key, root, &childIndex)==false)
                return false;
            out=root->data[childIndex];
            DeleteFromPageAtIndex(childIndex,root);
            if (root->size==0)
            {
                pagePool.Release(root, _FILE_AND_LINE_);
                root=0;
                leftmostLeaf=0;
            }
            return true;
        }
        else if (FindDeleteRebalance(key, root, &underflow,root->keys[0], &returnAction, out)==false)
            return false;

//      RakAssert(returnAction.action==ReturnAction::NO_ACTION);

        if (underflow && root->size==0)
        {
            // Move the root down.
            Page<KeyType, DataType, order> *oldRoot=root;
            root=root->children[0];
            pagePool.Release(oldRoot, _FILE_AND_LINE_);
            // memset(oldRoot,0,sizeof(root));
        }       
    
        return true;
    }
template<class KeyType, class DataType , int order>
bool DataStructures::BPlusTree< KeyType, DataType, order >::Delete ( const KeyType  key)

Definition at line 171 of file DS_BPlusTree.h.

    {
        DataType temp;
        return Delete(key, temp);
    }
template<class KeyType, class DataType, int order>
void DataStructures::BPlusTree< KeyType, DataType, order >::DeleteFromPageAtIndex ( const int  index,
Page< KeyType, DataType, order > *  cur 
) [protected]

Definition at line 153 of file DS_BPlusTree.h.

References DataStructures::Page< KeyType, DataType, order >::children, DataStructures::Page< KeyType, DataType, order >::data, if(), DataStructures::Page< KeyType, DataType, order >::isLeaf, DataStructures::Page< KeyType, DataType, order >::keys, and DataStructures::Page< KeyType, DataType, order >::size.

    {
        int i;
        for (i=index; i < cur->size-1; i++)
            cur->keys[i]=cur->keys[i+1];
        if (cur->isLeaf)
        {
            for (i=index; i < cur->size-1; i++)
                cur->data[i]=cur->data[i+1];
        }
        else
        {
            for (i=index; i < cur->size-1; i++)
                cur->children[i+1]=cur->children[i+2];
        }
        cur->size--;
    }
template<class KeyType, class DataType, int order>
bool DataStructures::BPlusTree< KeyType, DataType, order >::FindDeleteRebalance ( const KeyType  key,
Page< KeyType, DataType, order > *  cur,
bool underflow,
KeyType  rightRootKey,
ReturnAction returnAction,
DataType &  out 
) [protected]

Definition at line 217 of file DS_BPlusTree.h.

References DataStructures::BPlusTree< KeyType, DataType, order >::ReturnAction::action, DataStructures::Page< KeyType, DataType, order >::children, DataStructures::Page< KeyType, DataType, order >::data, DataStructures::Page< KeyType, DataType, order >::isLeaf, DataStructures::BPlusTree< KeyType, DataType, order >::ReturnAction::key1, DataStructures::Page< KeyType, DataType, order >::keys, and DataStructures::Page< KeyType, DataType, order >::size.

    {
        // Get index of child to follow.
        int branchIndex, childIndex;
        if (GetIndexOf(key, cur, &childIndex))
            branchIndex=childIndex+1;
        else
            branchIndex=childIndex;

        // If child is not a leaf, call recursively
        if (cur->children[branchIndex]->isLeaf==false)
        {
            if (branchIndex<cur->size)
                rightRootKey=cur->keys[branchIndex]; // Shift right to left
            else
                rightRootKey=cur->keys[branchIndex-1]; // Shift center to left

            if (FindDeleteRebalance(key, cur->children[branchIndex], underflow, rightRootKey, returnAction, out)==false)
                return false;

            // Call again in case the root key changed
            if (branchIndex<cur->size)
                rightRootKey=cur->keys[branchIndex]; // Shift right to left
            else
                rightRootKey=cur->keys[branchIndex-1]; // Shift center to left

            if (returnAction->action==ReturnAction::SET_BRANCH_KEY && branchIndex!=childIndex)
            {
                returnAction->action=ReturnAction::NO_ACTION;
                cur->keys[childIndex]=returnAction->key1;

                if (branchIndex<cur->size)
                    rightRootKey=cur->keys[branchIndex]; // Shift right to left
                else
                    rightRootKey=cur->keys[branchIndex-1]; // Shift center to left
            }
        }
        else
        {
            // If child is a leaf, get the index of the key.  If the item is not found, cancel delete.
            if (GetIndexOf(key, cur->children[branchIndex], &childIndex)==false)
                return false;

            // Delete:
            // Remove childIndex from the child at branchIndex
            out=cur->children[branchIndex]->data[childIndex];
            DeleteFromPageAtIndex(childIndex, cur->children[branchIndex]);

            if (childIndex==0)
            {
                if (branchIndex>0)
                    cur->keys[branchIndex-1]=cur->children[branchIndex]->keys[0];

                if (branchIndex==0)
                {
                    returnAction->action=ReturnAction::SET_BRANCH_KEY;
                    returnAction->key1=cur->children[0]->keys[0];
                }               
            }

            if (cur->children[branchIndex]->size < order/2)
                *underflow=true;
            else
                *underflow=false;
        }

        // Fix underflow:
        if (*underflow)
        {
            *underflow=FixUnderflow(branchIndex, cur, rightRootKey, returnAction);
        }

        return true;
    }
template<class KeyType, class DataType, int order>
bool DataStructures::BPlusTree< KeyType, DataType, order >::FixUnderflow ( int  branchIndex,
Page< KeyType, DataType, order > *  cur,
KeyType  rightRootKey,
ReturnAction returnAction 
) [protected]

Definition at line 292 of file DS_BPlusTree.h.

References _FILE_AND_LINE_, DataStructures::BPlusTree< KeyType, DataType, order >::ReturnAction::action, DataStructures::Page< KeyType, DataType, order >::children, DataStructures::Page< KeyType, DataType, order >::data, DataStructures::Page< KeyType, DataType, order >::isLeaf, DataStructures::BPlusTree< KeyType, DataType, order >::ReturnAction::key1, DataStructures::Page< KeyType, DataType, order >::keys, DataStructures::Page< KeyType, DataType, order >::next, DataStructures::Page< KeyType, DataType, order >::previous, and DataStructures::Page< KeyType, DataType, order >::size.

    {
        // Borrow from a neighbor that has excess.
        Page<KeyType, DataType, order> *source;
        Page<KeyType, DataType, order> *dest;

        if (branchIndex>0 && cur->children[branchIndex-1]->size > order/2)
        {
            dest=cur->children[branchIndex];
            source=cur->children[branchIndex-1];

            // Left has excess
            ShiftNodeRight(dest);
            if (dest->isLeaf)
            {
                dest->keys[0]=source->keys[source->size-1];
                dest->data[0]=source->data[source->size-1];
            }
            else
            {
                dest->children[0]=source->children[source->size];
                dest->keys[0]=cur->keys[branchIndex-1];
            }
            // Update the parent key for the child (middle)
            cur->keys[branchIndex-1]=source->keys[source->size-1];
            source->size--;

    //      if (branchIndex==0)
    //      {
    //          returnAction->action=ReturnAction::SET_BRANCH_KEY;
    //          returnAction->key1=dest->keys[0];
    //      }

            // No underflow
            return false;
        }
        else if (branchIndex<cur->size && cur->children[branchIndex+1]->size > order/2)
        {
            dest=cur->children[branchIndex];
            source=cur->children[branchIndex+1];

            // Right has excess
            if (dest->isLeaf)
            {
                dest->keys[dest->size]=source->keys[0];
                dest->data[dest->size]=source->data[0];

                // The first key in the leaf after shifting is the parent key for the right branch
                cur->keys[branchIndex]=source->keys[1];

#ifdef _MSC_VER
#pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
#endif
                if (order<=3 && dest->size==0)
                {
                    if (branchIndex==0)
                    {
                        returnAction->action=ReturnAction::SET_BRANCH_KEY;
                        returnAction->key1=dest->keys[0];
                    }
                    else
                        cur->keys[branchIndex-1]=cur->children[branchIndex]->keys[0];
                }
            }
            else
            {
                if (returnAction->action==ReturnAction::NO_ACTION)
                {
                    returnAction->action=ReturnAction::SET_BRANCH_KEY;
                    returnAction->key1=dest->keys[0];
                }
                
                dest->keys[dest->size]=rightRootKey;
                dest->children[dest->size+1]=source->children[0];

                // The shifted off key is the leftmost key for a node
                cur->keys[branchIndex]=source->keys[0];
            }


            dest->size++;
            ShiftNodeLeft(source);

            //cur->keys[branchIndex]=source->keys[0];

//          returnAction->action=ReturnAction::SET_BRANCH_KEY;
//          returnAction->key1=dest->keys[dest->size-1];

            // No underflow
            return false;
        }
        else
        {
            int sourceIndex;

            // If no neighbors have excess, merge two branches.
            //
            // To merge two leaves, just copy the data and keys over.
            //
            // To merge two branches, copy the pointers and keys over, using rightRootKey as the key for the extra pointer
            if (branchIndex<cur->size)
            {
                // Merge right child to current child and delete right child.
                dest=cur->children[branchIndex];
                source=cur->children[branchIndex+1];
            }
            else
            {
                // Move current child to left and delete current child
                dest=cur->children[branchIndex-1];
                source=cur->children[branchIndex];
            }

            // Merge
            if (dest->isLeaf)
            {
                for (sourceIndex=0; sourceIndex<source->size; sourceIndex++)
                {
                    dest->keys[dest->size]=source->keys[sourceIndex];
                    dest->data[dest->size++]=source->data[sourceIndex];
                }
            }
            else
            {
                // We want the tree root key of the source, not the current.
                dest->keys[dest->size]=rightRootKey;
                dest->children[dest->size++ + 1]=source->children[0];
                for (sourceIndex=0; sourceIndex<source->size; sourceIndex++)
                {
                    dest->keys[dest->size]=source->keys[sourceIndex];
                    dest->children[dest->size++ + 1]=source->children[sourceIndex + 1];
                }
            }

#ifdef _MSC_VER
#pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
#endif
            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.
                cur->keys[branchIndex-1]=cur->children[branchIndex]->keys[0];

            if (branchIndex<cur->size)
            {
                // Update the parent key, removing the source (right)
                DeleteFromPageAtIndex(branchIndex, cur);
            }
            else
            {
                if (branchIndex>0)
                {
                    // Update parent key, removing the source (current)
                    DeleteFromPageAtIndex(branchIndex-1, cur);
                }
            }

            if (branchIndex==0 && dest->isLeaf)
            {
                returnAction->action=ReturnAction::SET_BRANCH_KEY;
                returnAction->key1=dest->keys[0];
            }

            if (source==leftmostLeaf)
                leftmostLeaf=source->next;

            if (source->isLeaf)
            {
                if (source->previous)
                    source->previous->next=source->next;
                if (source->next)
                    source->next->previous=source->previous;
            }           

            // Free the source node
            pagePool.Release(source, _FILE_AND_LINE_);
            // memset(source,0,sizeof(root));

            // Return underflow or not of parent.
            return cur->size < order/2;
        }
    }
template<class KeyType , class DataType, int order>
void DataStructures::BPlusTree< KeyType, DataType, order >::ForEachData ( void(*)(DataType input, int index)  func)
template<class KeyType, class DataType, int order>
void DataStructures::BPlusTree< KeyType, DataType, order >::ForEachLeaf ( void(*)(Page< KeyType, DataType, order > *leaf, int index)  func)

Definition at line 967 of file DS_BPlusTree.h.

References DataStructures::Page< KeyType, DataType, order >::next.

    {
        int count=0;
        DataStructures::Page<KeyType, DataType, order> *cur = GetListHead();
        while (cur)
        {
            func(cur, count++);
            cur=cur->next;
        }
    }
template<class KeyType , class DataType , int order>
void DataStructures::BPlusTree< KeyType, DataType, order >::FreePages ( void  ) [protected]
template<class KeyType, class DataType, int order>
bool DataStructures::BPlusTree< KeyType, DataType, order >::Get ( const KeyType  key,
DataType &  out 
) const

Definition at line 137 of file DS_BPlusTree.h.

References DataStructures::Page< KeyType, DataType, order >::data.

    {
        if (root==0)
            return false;

        Page<KeyType, DataType, order>* leaf = GetLeafFromKey(key);
        int childIndex;
        
        if (GetIndexOf(key, leaf, &childIndex))
        {
            out=leaf->data[childIndex];
            return true;
        }
        return false;
    }
template<class KeyType , class DataType , int order>
DataType DataStructures::BPlusTree< KeyType, DataType, order >::GetDataHead ( void  ) const

Definition at line 962 of file DS_BPlusTree.h.

    {
        return leftmostLeaf->data[0];
    }
template<class KeyType, class DataType, int order>
bool DataStructures::BPlusTree< KeyType, DataType, order >::GetIndexOf ( const KeyType  key,
Page< KeyType, DataType, order > *  page,
int *  out 
) const [protected]

Definition at line 905 of file DS_BPlusTree.h.

References DataStructures::Page< KeyType, DataType, order >::keys, RakAssert, and DataStructures::Page< KeyType, DataType, order >::size.

    {
        RakAssert(page->size>0);
        int index, upperBound, lowerBound;
        upperBound=page->size-1;
        lowerBound=0;
        index = page->size/2;

#ifdef _MSC_VER
#pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
#endif
        while (1)
        {
            if (key==page->keys[index])
            {
                *out=index;
                return true;
            }
            else if (key<page->keys[index])
                upperBound=index-1;
            else
                lowerBound=index+1;

            index=lowerBound+(upperBound-lowerBound)/2;

            if (lowerBound>upperBound)
            {
                *out=lowerBound;
                return false; // No match
            }
        }
    }
template<class KeyType, class DataType , int order>
Page< KeyType, DataType, order > * DataStructures::BPlusTree< KeyType, DataType, order >::GetLeafFromKey ( const KeyType  key) const [protected]

Definition at line 699 of file DS_BPlusTree.h.

References DataStructures::Page< KeyType, DataType, order >::children, and DataStructures::Page< KeyType, DataType, order >::isLeaf.

    {
        Page<KeyType, DataType, order>* cur = root;
        int childIndex;
        while (cur->isLeaf==false)
        {
            // When searching, if we match the exact key we go down the pointer after that index
            if (GetIndexOf(key, cur, &childIndex))
                childIndex++;
            cur = cur->children[childIndex];
        }
        return cur;
    }
template<class KeyType , class DataType , int order>
Page< KeyType, DataType, order > * DataStructures::BPlusTree< KeyType, DataType, order >::GetListHead ( void  ) const

Definition at line 957 of file DS_BPlusTree.h.

    {
        return leftmostLeaf;
    }
template<class KeyType, class DataType, int order>
bool DataStructures::BPlusTree< KeyType, DataType, order >::Insert ( const KeyType  key,
const DataType &  data 
)

Definition at line 822 of file DS_BPlusTree.h.

References _FILE_AND_LINE_, DataStructures::BPlusTree< KeyType, DataType, order >::ReturnAction::action, DataStructures::Page< KeyType, DataType, order >::children, DataStructures::Page< KeyType, DataType, order >::isLeaf, DataStructures::BPlusTree< KeyType, DataType, order >::ReturnAction::key1, DataStructures::Page< KeyType, DataType, order >::keys, RakAssert, and DataStructures::Page< KeyType, DataType, order >::size.

    {
        if (root==0)
        {
            // Allocate root and make root a leaf
            root = pagePool.Allocate( _FILE_AND_LINE_ );
            root->isLeaf=true;
            leftmostLeaf=root;
            root->size=1;
            root->keys[0]=key;
            root->data[0]=data;
            root->next=0;
            root->previous=0;
        }
        else
        {
            bool success=true;
            ReturnAction returnAction;
            returnAction.action=ReturnAction::NO_ACTION;
            Page<KeyType, DataType, order>* newPage = InsertBranchDown(key, data, root, &returnAction, &success);
            if (success==false)
                return false;
            if (newPage)
            {
                KeyType newKey;
                if (newPage->isLeaf==false)
                {
                    // 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
                    RakAssert(returnAction.action==ReturnAction::PUSH_KEY_TO_PARENT);
                    newKey=returnAction.key1;
                    newPage->size--;
                }
                else
                     newKey = newPage->keys[0];
                // propagate the root
                Page<KeyType, DataType, order>* newRoot = pagePool.Allocate( _FILE_AND_LINE_ );
                newRoot->isLeaf=false;
                newRoot->size=1;
                newRoot->keys[0]=newKey;
                newRoot->children[0]=root;
                newRoot->children[1]=newPage;
                root=newRoot;
            }
        }

        return true;
    }
template<class KeyType, class DataType, int order>
Page< KeyType, DataType, order > * DataStructures::BPlusTree< KeyType, DataType, order >::InsertBranchDown ( const KeyType  key,
const DataType &  data,
Page< KeyType, DataType, order > *  cur,
ReturnAction returnAction,
bool success 
) [protected]

Definition at line 714 of file DS_BPlusTree.h.

References DataStructures::BPlusTree< KeyType, DataType, order >::ReturnAction::action, DataStructures::Page< KeyType, DataType, order >::children, DataStructures::Page< KeyType, DataType, order >::data, DataStructures::Page< KeyType, DataType, order >::isLeaf, DataStructures::BPlusTree< KeyType, DataType, order >::ReturnAction::key1, DataStructures::BPlusTree< KeyType, DataType, order >::ReturnAction::key2, DataStructures::Page< KeyType, DataType, order >::keys, RakAssert, and DataStructures::Page< KeyType, DataType, order >::size.

    {
        int childIndex;
        int branchIndex;
        if (GetIndexOf(key, cur, &childIndex))
            branchIndex=childIndex+1;
        else
            branchIndex=childIndex;
        Page<KeyType, DataType, order>* newPage;
        if (cur->isLeaf==false)
        {
            if (cur->children[branchIndex]->isLeaf==true && cur->children[branchIndex]->size==order)
            {
                if (branchIndex==childIndex+1)
                {
                    *success=false;
                    return 0; // Already exists
                }

                if (CanRotateLeft(cur, branchIndex))
                {
                    returnAction->action=ReturnAction::REPLACE_KEY1_WITH_KEY2;
                    if (key > cur->children[branchIndex]->keys[0])
                    {                       
                        RotateLeft(cur, branchIndex, returnAction);

                        int insertionIndex;
                        GetIndexOf(key, cur->children[branchIndex], &insertionIndex);
                        InsertIntoNode(key, data, insertionIndex, 0, cur->children[branchIndex], 0);
                    }
                    else
                    {
                        // Move head element to left and replace it with key,data
                        Page<KeyType, DataType, order>* dest=cur->children[branchIndex-1];
                        Page<KeyType, DataType, order>* source=cur->children[branchIndex];
                        returnAction->key1=source->keys[0];
                        returnAction->key2=key;
                        dest->keys[dest->size]=source->keys[0];
                        dest->data[dest->size]=source->data[0];
                        dest->size++;
                        source->keys[0]=key;
                        source->data[0]=data;   
                    }
                    cur->keys[branchIndex-1]=cur->children[branchIndex]->keys[0];
                    
                    return 0;
                }
                else if (CanRotateRight(cur, branchIndex))
                {
                    returnAction->action=ReturnAction::REPLACE_KEY1_WITH_KEY2;
                    
                    if (key < cur->children[branchIndex]->keys[cur->children[branchIndex]->size-1])
                    {
                        RotateRight(cur, branchIndex, returnAction);

                        int insertionIndex;
                        GetIndexOf(key, cur->children[branchIndex], &insertionIndex);
                        InsertIntoNode(key, data, insertionIndex, 0, cur->children[branchIndex], 0);
                        
                    }
                    else
                    {
                        // Insert to the head of the right leaf instead and change our key
                        returnAction->key1=cur->children[branchIndex+1]->keys[0];
                        InsertIntoNode(key, data, 0, 0, cur->children[branchIndex+1], 0);                       
                        returnAction->key2=key;
                    }
                    cur->keys[branchIndex]=cur->children[branchIndex+1]->keys[0];
                    return 0;                   
                }
            }

            newPage=InsertBranchDown(key,data,cur->children[branchIndex], returnAction, success);
            if (returnAction->action==ReturnAction::REPLACE_KEY1_WITH_KEY2)
            {
                if (branchIndex>0 && cur->keys[branchIndex-1]==returnAction->key1)
                    cur->keys[branchIndex-1]=returnAction->key2;
            }
            if (newPage)
            {
                if (newPage->isLeaf==false)
                {
                    RakAssert(returnAction->action==ReturnAction::PUSH_KEY_TO_PARENT);
                    newPage->size--; 
                    return InsertIntoNode(returnAction->key1, data, branchIndex, newPage, cur, returnAction);
                }
                else
                {
                    return InsertIntoNode(newPage->keys[0], data, branchIndex, newPage, cur, returnAction);
                }               
            }
        }
        else
        {
            if (branchIndex==childIndex+1)
            {
                *success=false;
                return 0; // Already exists             
            }
            else
            {
                return InsertIntoNode(key, data, branchIndex, 0, cur, returnAction);
            }
        }
        
        return 0;
    }
template<class KeyType, class DataType, int order>
Page< KeyType, DataType, order > * DataStructures::BPlusTree< KeyType, DataType, order >::InsertIntoNode ( const KeyType  key,
const DataType &  childData,
int  insertionIndex,
Page< KeyType, DataType, order > *  nodeData,
Page< KeyType, DataType, order > *  cur,
ReturnAction returnAction 
) [protected]

Definition at line 509 of file DS_BPlusTree.h.

References _FILE_AND_LINE_, DataStructures::BPlusTree< KeyType, DataType, order >::ReturnAction::action, DataStructures::Page< KeyType, DataType, order >::children, DataStructures::Page< KeyType, DataType, order >::data, if(), DataStructures::Page< KeyType, DataType, order >::isLeaf, DataStructures::BPlusTree< KeyType, DataType, order >::ReturnAction::key1, DataStructures::Page< KeyType, DataType, order >::keys, DataStructures::Page< KeyType, DataType, order >::next, DataStructures::Page< KeyType, DataType, order >::previous, RakAssert, and DataStructures::Page< KeyType, DataType, order >::size.

    {
        int i;
        if (cur->size < order)
        {
            for (i=cur->size; i > insertionIndex; i--)
                cur->keys[i]=cur->keys[i-1];
            if (cur->isLeaf)
            {
                for (i=cur->size; i > insertionIndex; i--)
                    cur->data[i]=cur->data[i-1];
            }
            else
            {
                for (i=cur->size+1; i > insertionIndex+1; i--)
                    cur->children[i]=cur->children[i-1];
            }
            cur->keys[insertionIndex]=key;
            if (cur->isLeaf)
                cur->data[insertionIndex]=leafData;
            else
                cur->children[insertionIndex+1]=nodeData;

            cur->size++;
        }
        else
        {
            Page<KeyType, DataType, order>* newPage = pagePool.Allocate( _FILE_AND_LINE_ );
            newPage->isLeaf=cur->isLeaf;
            if (cur->isLeaf)
            {
                newPage->next=cur->next;
                if (cur->next)
                    cur->next->previous=newPage;
                newPage->previous=cur;
                cur->next=newPage;
            }

            int destIndex, sourceIndex;

            if (insertionIndex>=(order+1)/2)
            {
                destIndex=0;
                sourceIndex=order/2;

                for (; sourceIndex < insertionIndex; sourceIndex++, destIndex++)
                {
                    newPage->keys[destIndex]=cur->keys[sourceIndex];
                }
                newPage->keys[destIndex++]=key;
                for (; sourceIndex < order; sourceIndex++, destIndex++)
                {
                    newPage->keys[destIndex]=cur->keys[sourceIndex];
                }

                destIndex=0;
                sourceIndex=order/2;
                if (cur->isLeaf)
                {
                    for (; sourceIndex < insertionIndex; sourceIndex++, destIndex++)
                    {
                        newPage->data[destIndex]=cur->data[sourceIndex];
                    }
                    newPage->data[destIndex++]=leafData;
                    for (; sourceIndex < order; sourceIndex++, destIndex++)
                    {
                        newPage->data[destIndex]=cur->data[sourceIndex];
                    }
                }
                else
                {
                    
                    for (; sourceIndex < insertionIndex; sourceIndex++, destIndex++)
                    {
                        newPage->children[destIndex]=cur->children[sourceIndex+1];
                    }
                    newPage->children[destIndex++]=nodeData;

                    // sourceIndex+1 is sort of a hack but it works - because there is one extra child than keys
                    // skip past the last child for cur
                    for (; sourceIndex+1 < cur->size+1; sourceIndex++, destIndex++)
                    {
                        newPage->children[destIndex]=cur->children[sourceIndex+1];
                    }

                    // the first key is the middle key.  Remove it from the page and push it to the parent
                    returnAction->action=ReturnAction::PUSH_KEY_TO_PARENT;
                    returnAction->key1=newPage->keys[0];
                    for (int i=0; i < destIndex-1; i++)
                        newPage->keys[i]=newPage->keys[i+1];
                    
                }
                cur->size=order/2;
            }
            else
            {
                destIndex=0;
                sourceIndex=(order+1)/2-1;
                for (; sourceIndex < order; sourceIndex++, destIndex++)
                    newPage->keys[destIndex]=cur->keys[sourceIndex];
                destIndex=0;
                if (cur->isLeaf)
                {
                    sourceIndex=(order+1)/2-1;
                    for (; sourceIndex < order; sourceIndex++, destIndex++)
                        newPage->data[destIndex]=cur->data[sourceIndex];
                }
                else
                {
                    sourceIndex=(order+1)/2;
                    for (; sourceIndex < order+1; sourceIndex++, destIndex++)
                        newPage->children[destIndex]=cur->children[sourceIndex];

                    // the first key is the middle key.  Remove it from the page and push it to the parent
                    returnAction->action=ReturnAction::PUSH_KEY_TO_PARENT;
                    returnAction->key1=newPage->keys[0];
                    for (int i=0; i < destIndex-1; i++)
                        newPage->keys[i]=newPage->keys[i+1];
                }
                cur->size=(order+1)/2-1;
                if (cur->size)
                {
                    bool b = GetIndexOf(key, cur, &insertionIndex);
                    (void) b;
                    RakAssert(b==false);
                }
                else
                    insertionIndex=0;
                InsertIntoNode(key, leafData, insertionIndex, nodeData, cur, returnAction);
            }

            newPage->size=destIndex;

            return newPage;
        }

        return 0;
    }
template<class KeyType , class DataType , int order>
bool DataStructures::BPlusTree< KeyType, DataType, order >::IsEmpty ( void  ) const

Definition at line 900 of file DS_BPlusTree.h.

    {
        return root==0;
    }
template<class KeyType , class DataType , int order>
void DataStructures::BPlusTree< KeyType, DataType, order >::PrintGraph ( void  )
template<class KeyType, class DataType, int order>
void DataStructures::BPlusTree< KeyType, DataType, order >::PrintLeaf ( Page< KeyType, DataType, order > *  leaf,
int  index 
) [static, protected]

Definition at line 990 of file DS_BPlusTree.h.

References DataStructures::Page< KeyType, DataType, order >::data, RAKNET_DEBUG_PRINTF, and DataStructures::Page< KeyType, DataType, order >::size.

    {
        int i;
        RAKNET_DEBUG_PRINTF("%i] SELF=%p\n", index+1, leaf);
        for (i=0; i < leaf->size; i++)
            RAKNET_DEBUG_PRINTF(" %i. %i\n", i+1, leaf->data[i]);
    }
template<class KeyType , class DataType , int order>
void DataStructures::BPlusTree< KeyType, DataType, order >::PrintLeaves ( void  )

Definition at line 998 of file DS_BPlusTree.h.

template<class KeyType, class DataType, int order>
void DataStructures::BPlusTree< KeyType, DataType, order >::RotateLeft ( Page< KeyType, DataType, order > *  cur,
int  childIndex,
ReturnAction returnAction 
) [protected]

Definition at line 655 of file DS_BPlusTree.h.

References DataStructures::Page< KeyType, DataType, order >::children, DataStructures::Page< KeyType, DataType, order >::data, DataStructures::BPlusTree< KeyType, DataType, order >::ReturnAction::key1, DataStructures::BPlusTree< KeyType, DataType, order >::ReturnAction::key2, DataStructures::Page< KeyType, DataType, order >::keys, and DataStructures::Page< KeyType, DataType, order >::size.

    {
        Page<KeyType, DataType, order> *dest = cur->children[childIndex-1];
        Page<KeyType, DataType, order> *source = cur->children[childIndex];
        returnAction->key1=source->keys[0];
        dest->keys[dest->size]=source->keys[0];
        dest->data[dest->size]=source->data[0];
        dest->size++;
        for (int i=0; i < source->size-1; i++)
        {
            source->keys[i]=source->keys[i+1];
            source->data[i]=source->data[i+1];
        }
        source->size--;
        cur->keys[childIndex-1]=source->keys[0];
        returnAction->key2=source->keys[0];
    }
template<class KeyType, class DataType, int order>
void DataStructures::BPlusTree< KeyType, DataType, order >::RotateRight ( Page< KeyType, DataType, order > *  cur,
int  childIndex,
ReturnAction returnAction 
) [protected]

Definition at line 680 of file DS_BPlusTree.h.

References DataStructures::Page< KeyType, DataType, order >::children, DataStructures::Page< KeyType, DataType, order >::data, DataStructures::BPlusTree< KeyType, DataType, order >::ReturnAction::key1, DataStructures::BPlusTree< KeyType, DataType, order >::ReturnAction::key2, DataStructures::Page< KeyType, DataType, order >::keys, and DataStructures::Page< KeyType, DataType, order >::size.

    {
        Page<KeyType, DataType, order> *dest = cur->children[childIndex+1];
        Page<KeyType, DataType, order> *source = cur->children[childIndex];
        returnAction->key1=dest->keys[0];
        for (int i= dest->size; i > 0; i--)
        {
            dest->keys[i]=dest->keys[i-1];
            dest->data[i]=dest->data[i-1];
        }
        dest->keys[0]=source->keys[source->size-1];
        dest->data[0]=source->data[source->size-1];
        dest->size++;
        source->size--;

        cur->keys[childIndex]=dest->keys[0];
        returnAction->key2=dest->keys[0];
    }
template<class KeyType , class DataType , int order>
void DataStructures::BPlusTree< KeyType, DataType, order >::SetPoolPageSize ( int  size)

Definition at line 132 of file DS_BPlusTree.h.

    {
        pagePool.SetPageSize(size);
    }
template<class KeyType, class DataType, int order>
void DataStructures::BPlusTree< KeyType, DataType, order >::ShiftKeysLeft ( Page< KeyType, DataType, order > *  cur) [protected]

Definition at line 870 of file DS_BPlusTree.h.

References DataStructures::Page< KeyType, DataType, order >::keys, and DataStructures::Page< KeyType, DataType, order >::size.

    {
        int i;
        for (i=0; i < cur->size; i++)
            cur->keys[i]=cur->keys[i+1];
    }
template<class KeyType, class DataType, int order>
void DataStructures::BPlusTree< KeyType, DataType, order >::ShiftNodeLeft ( Page< KeyType, DataType, order > *  cur) [protected]

Definition at line 491 of file DS_BPlusTree.h.

References DataStructures::Page< KeyType, DataType, order >::children, DataStructures::Page< KeyType, DataType, order >::data, if(), DataStructures::Page< KeyType, DataType, order >::isLeaf, DataStructures::Page< KeyType, DataType, order >::keys, and DataStructures::Page< KeyType, DataType, order >::size.

    {
        int i;
        for (i=0; i < cur->size-1; i++)
            cur->keys[i]=cur->keys[i+1];
        if (cur->isLeaf)
        {
            for (i=0; i < cur->size; i++)
                cur->data[i]=cur->data[i+1];
        }
        else
        {
            for (i=0; i < cur->size; i++)
                cur->children[i]=cur->children[i+1];
        }
        cur->size--;
    }
template<class KeyType, class DataType, int order>
void DataStructures::BPlusTree< KeyType, DataType, order >::ShiftNodeRight ( Page< KeyType, DataType, order > *  cur) [protected]

Definition at line 472 of file DS_BPlusTree.h.

References DataStructures::Page< KeyType, DataType, order >::children, DataStructures::Page< KeyType, DataType, order >::data, DataStructures::Page< KeyType, DataType, order >::isLeaf, DataStructures::Page< KeyType, DataType, order >::keys, and DataStructures::Page< KeyType, DataType, order >::size.

    {
        int i;
        for (i=cur->size; i>0; i--)
            cur->keys[i]=cur->keys[i-1];
        if (cur->isLeaf)
        {
            for (i=cur->size; i>0; i--)
                cur->data[i]=cur->data[i-1];
        }
        else
        {
            for (i=cur->size+1; i>0; i--)
                cur->children[i]=cur->children[i-1];
        }

        cur->size++;
    }
template<class KeyType , class DataType , int order>
unsigned DataStructures::BPlusTree< KeyType, DataType, order >::Size ( void  ) const

Definition at line 888 of file DS_BPlusTree.h.

References DataStructures::Page< KeyType, DataType, order >::next, and DataStructures::Page< KeyType, DataType, order >::size.

    {
        int count=0;
        DataStructures::Page<KeyType, DataType, order> *cur = GetListHead();
        while (cur)
        {
            count+=cur->size;
            cur=cur->next;
        }
        return count;
    }
template<class KeyType, class DataType, int order>
void DataStructures::BPlusTree< KeyType, DataType, order >::ValidateTreeRecursive ( Page< KeyType, DataType, order > *  cur) [protected]

Definition at line 1004 of file DS_BPlusTree.h.

References DataStructures::Page< KeyType, DataType, order >::children, DataStructures::Page< KeyType, DataType, order >::isLeaf, DataStructures::Page< KeyType, DataType, order >::keys, RakAssert, and DataStructures::Page< KeyType, DataType, order >::size.

    {
        RakAssert(cur==root || cur->size>=order/2);

        if (cur->children[0]->isLeaf)
        {
            RakAssert(cur->children[0]->keys[0] < cur->keys[0]);
            for (int i=0; i < cur->size; i++)
            {
                RakAssert(cur->children[i+1]->keys[0]==cur->keys[i]);
            }
        }
        else
        {
            for (int i=0; i < cur->size+1; i++)
                ValidateTreeRecursive(cur->children[i]);
        }
    }

Member Data Documentation

template<class KeyType, class DataType, int order>
Page<KeyType, DataType, order> * DataStructures::BPlusTree< KeyType, DataType, order >::leftmostLeaf [protected]

Definition at line 116 of file DS_BPlusTree.h.

template<class KeyType, class DataType, int order>
MemoryPool<Page<KeyType, DataType, order> > DataStructures::BPlusTree< KeyType, DataType, order >::pagePool [protected]

Definition at line 115 of file DS_BPlusTree.h.

template<class KeyType, class DataType, int order>
Page<KeyType, DataType, order>* DataStructures::BPlusTree< KeyType, DataType, order >::root [protected]

Definition at line 116 of file DS_BPlusTree.h.


The documentation for this class was generated from the following file:

Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.

GNU Lesser General Public License 3 Sourceforge.net