1. 程式人生 > >資料結構 B+樹c程式碼實現

資料結構 B+樹c程式碼實現

template<typename Type> class BTree;

template<typename Type> class BTreeNode{

public:

    friendBTree<Type>;

    BTreeNode(): m_nMaxSize(0),m_ptr(NULL), m_pparent(NULL){}

    BTreeNode(int size): m_nsize(0), m_nMaxSize(size),m_pparent(NULL){

        m_pkey = new Type[size+1];

        m_ptr = new

 BTreeNode<Type> *[size+1];

        for(int i=0; i<=size; i++){

            m_ptr[i] = NULL;

            m_pkey[i] = this->m_Infinity;

        }

    }

    voidDestroy(BTreeNode<Type> *root);

    ~BTreeNode(){

      if(m_nMaxSize){

        delete[]m_pkey;

        for(int i=0; i<=m_nMaxSize; i++){

           m_ptr[i] = NULL;

        }

      }

    }

    boolIsFull(){

        returnm_nsize == m_nMaxSize;

    }

    Type GetKey(int i){

        if(this){

            returnthis->m_pkey[i];

        }

        return-1;

    }

private:

    intm_nsize;

    intm_nMaxSize;     //theMax Size of key

    Type *m_pkey;

    BTreeNode<Type>*m_pparent;

    BTreeNode<Type> **m_ptr;

    staticconst Type m_Infinity = 10000;

};

template<typename Type> struct Triple{

    BTreeNode<Type> *m_pfind;

    intm_nfind;

    boolm_ntag;

};

template<typename Type> voidBTreeNode<Type>::Destroy(BTreeNode<Type> *root){

    if(NULL == root){

        return;

    }

    for(int i=0; i<root->m_nsize; i++){

        Destroy(root->m_ptr[i]);

    }

    deleteroot;

}

#include "BTreeNode.h"

template<typename Type> class BTree{

public:

    BTree(intsize): m_nMaxSize(size), m_proot(NULL){}

    ~BTree();

    Triple<Type> Search(const Type item);

    intSize();

    intSize(BTreeNode<Type> *root);

    boolInsert(const Type item);   //insert item

    boolRemove(const Type item);   //delete item

    voidPrint();                   //print the BTree

    BTreeNode<Type>*GetParent(const Type item);   

private:

    //insertthe pright and item to pinsert in the nth place;

    voidInsertKey(BTreeNode<Type> *pinsert, intn, const Type item, BTreeNode<Type>*pright);

    voidPreMove(BTreeNode<Type> *root, int n); //move ahead

    //mergethe child tree

    voidMerge(BTreeNode<Type> *pleft, BTreeNode<Type> *pparent,BTreeNode<Type> *pright, int n);

   //adjust with the parent and the left childtree

    voidLeftAdjust(BTreeNode<Type> *pright, BTreeNode<Type> *pparent, int min, int n);

    //adjustwith the parent and the left child tree

    voidRightAdjust(BTreeNode<Type> *pleft, BTreeNode<Type> *pparent, int min, int n);

    voidPrint(BTreeNode<Type> *start, int n = 0);

private:

    BTreeNode<Type> *m_proot;

    constint m_nMaxSize;

};

template<typename Type>BTree<Type>::~BTree(){

    m_proot->Destroy(m_proot);

}

template<typename Type>Triple<Type> BTree<Type>::Search(constType item){

    Triple<Type> result;

    BTreeNode<Type> *pmove =m_proot, *parent = NULL;

    inti = 0;

    while(pmove){

        i = -1;

        while(item > pmove->m_pkey[++i]); //find the suitposition

        if(pmove->m_pkey[i] == item){

            result.m_pfind = pmove;

            result.m_nfind = i;

            result.m_ntag = 1;

            returnresult;

        }

        parent = pmove;

        pmove =pmove->m_ptr[i];    //find in the child tree

   }

    result.m_pfind = parent;

    result.m_nfind = i;

    result.m_ntag = 0;

    returnresult;

}

template<typename Type> voidBTree<Type>::InsertKey(BTreeNode<Type> *pinsert, int n, const Typeitem, BTreeNode<Type> *pright){

    pinsert->m_nsize++;

   for (inti=pinsert->m_nsize; i>n; i--){

        pinsert->m_pkey[i] =pinsert->m_pkey[i-1];

        pinsert->m_ptr[i+1] =pinsert->m_ptr[i];

    }

    pinsert->m_pkey[n] = item;

    pinsert->m_ptr[n+1] = pright;

    if(pinsert->m_ptr[n+1]){       //change the right child tree's parent

       pinsert->m_ptr[n+1]->m_pparent = pinsert;

        for(int i=0;i<=pinsert->m_ptr[n+1]->m_nsize; i++){

            if(pinsert->m_ptr[n+1]->m_ptr[i]){

               pinsert->m_ptr[n+1]->m_ptr[i]->m_pparent = pinsert->m_ptr[n+1];

            }

        }

    }

}

template<typename Type> bool BTree<Type>::Insert(const Type item){

    if(NULL == m_proot){       //insert the first node

        m_proot = new BTreeNode<Type>(m_nMaxSize);

        m_proot->m_nsize = 1;

        m_proot->m_pkey[1] =m_proot->m_pkey[0];

        m_proot->m_pkey[0] =item;

        m_proot->m_ptr[0] =m_proot->m_ptr[1] =NULL;

        return1;

    }

    Triple<Type> find = this->Search(item); //searchthe position

    if(find.m_ntag){

        cerr << "Theitem is exist!" << endl;

        return0;

    }

    BTreeNode<Type> *pinsert =find.m_pfind, *newnode;

    BTreeNode<Type> *pright =NULL, *pparent;

    Type key = item;

    intn = find.m_nfind;

    while(1){

        if(pinsert->m_nsize < pinsert->m_nMaxSize-1){  //There is somespace

            InsertKey(pinsert, n,key, pright);

            return1;

        }

        intm = (pinsert->m_nsize + 1) / 2;     //get the middle item

        InsertKey(pinsert, n, key,pright);     //insertfirst, then break up

        newnode = new BTreeNode<Type>(this->m_nMaxSize);//create the newnode for break up

        //breakup

        for(int i=m+1; i<=pinsert->m_nsize;i++){     

           newnode->m_pkey[i-m-1] = pinsert->m_pkey[i];

            newnode->m_ptr[i-m-1] =pinsert->m_ptr[i];

            pinsert->m_pkey[i] =pinsert->m_Infinity;

            pinsert->m_ptr[i] =NULL;

        }

        newnode->m_nsize =pinsert->m_nsize - m - 1;

        pinsert->m_nsize = m;

        for(int i=0; i<=newnode->m_nsize; i++){    //change theparent

            if(newnode->m_ptr[i]){

               newnode->m_ptr[i]->m_pparent = newnode;

                for (int j=0;j<=newnode->m_ptr[i]->m_nsize; j++){

                    if (newnode->m_ptr[i]->m_ptr[j]){

                       newnode->m_ptr[i]->m_ptr[j]->m_pparent = newnode->m_ptr[i];

                    }

                }

            }

        }

        for(int i=0; i<=pinsert->m_nsize; i++){    //change theparent

            if(pinsert->m_ptr[i]){

               pinsert->m_ptr[i]->m_pparent = pinsert;

                for (int j=0;j<=pinsert->m_nsize; j++){

                    if (pinsert->m_ptr[i]->m_ptr[j]){

                       pinsert->m_ptr[i]->m_ptr[j]->m_pparent = pinsert->m_ptr[i];

                    }

                }

            }

        }

        //breakup over

        key = pinsert->m_pkey[m];

        pright = newnode;

        if(pinsert->m_pparent){    //insert the key to the parent

            pparent = pinsert->m_pparent;

            n = -1;

           pparent->m_pkey[pparent->m_nsize] = pparent->m_Infinity;

            while(key > pparent->m_pkey[++n]);

            newnode->m_pparent =pinsert->m_pparent;

            pinsert = pparent;

        }

        else{              //createnew root

            m_proot = new BTreeNode<Type>(this->m_nMaxSize);

            m_proot->m_nsize = 1;

            m_proot->m_pkey[1] =m_proot->m_pkey[0];

            m_proot->m_pkey[0] =key;

            m_proot->m_ptr[0] =pinsert;

            m_proot->m_ptr[1] =pright;

            newnode->m_pparent =pinsert->m_pparent = m_proot;

            return1;

        }

    }

}

template<typename Type> void BTree<Type>::PreMove(BTreeNode<Type>*root, int n){

    root->m_pkey[root->m_nsize]= root->m_Infinity;

    for(int i=n; i<root->m_nsize; i++){

        root->m_pkey[i] =root->m_pkey[i+1];

        root->m_ptr[i+1] =root->m_ptr[i+2];

    }

    root->m_nsize--;

}

template<typename Type> void BTree<Type>::Merge(BTreeNode<Type>*pleft, BTreeNode<Type> *pparent, BTreeNode<Type> *pright, int n){

   pleft->m_pkey[pleft->m_nsize] = pparent->m_pkey[n];

    BTreeNode<Type> *ptemp;

    for(int i=0; i<=pright->m_nsize; i++){ //merge the two child tree and the parent

        pleft->m_pkey[pleft->m_nsize+i+1]= pright->m_pkey[i];

       pleft->m_ptr[pleft->m_nsize+i+1] = pright->m_ptr[i];

        ptemp =pleft->m_ptr[pleft->m_nsize+i+1];

        if(ptemp){         //changethd right child tree's parent

            ptemp->m_pparent = pleft;

            for(int j=0; j<=ptemp->m_nsize; j++){

                if (ptemp->m_ptr[j]){

                   ptemp->m_ptr[j]->m_pparent = ptemp;

                }

            }

        }

    }

    pleft->m_nsize =pleft->m_nsize + pright->m_nsize + 1;

    deletepright;

    PreMove(pparent, n);   

//   this->Print();

}

template<typename Type> voidBTree<Type>::LeftAdjust(BTreeNode<Type> *pright,BTreeNode<Type> *pparent, int min, int n){

    BTreeNode<Type> *pleft =pparent->m_ptr[n-1], *ptemp;

    if(pleft->m_nsize > min-1){

        for(int i=pright->m_nsize+1; i>0; i--){

            pright->m_pkey[i] =pright->m_pkey[i-1];

            pright->m_ptr[i] =pright->m_ptr[i-1];

        }

        pright->m_pkey[0] =pparent->m_pkey[n-1];

        pright->m_ptr[0] =pleft->m_ptr[pleft->m_nsize];

        ptemp = pright->m_ptr[0];

        if(ptemp){     //changethe tree's parent which is moved

            ptemp->m_pparent =pright;

            for(int i=0; i<ptemp->m_nsize; i++){

                if(ptemp->m_ptr[i]){

                   ptemp->m_ptr[i]->m_pparent = ptemp;

                }

            }

        }

        pparent->m_pkey[n-1] =pleft->m_pkey[pleft->m_nsize-1];

       pleft->m_pkey[pleft->m_nsize] = pleft->m_Infinity;

        pleft->m_nsize--;

        pright->m_nsize++;

    }

    else{

        Merge(pleft, pparent,pright, n-1);

    }

//      this->Print();

}

template<typename Type> voidBTree<Type>::RightAdjust(BTreeNode<Type> *pleft,BTreeNode<Type> *pparent, int min, int n){

    BTreeNode<Type> *pright =pparent->m_ptr[1], *ptemp;

    if(pright && pright->m_nsize > min-1){

       pleft->m_pkey[pleft->m_nsize] = pparent->m_pkey[0];

        pparent->m_pkey[0] =pright->m_pkey[0];

       pleft->m_ptr[pleft->m_nsize+1] = pright->m_ptr[0];

        ptemp =pleft->m_ptr[pleft->m_nsize+1];

        if(ptemp){         //changethe tree's parent which is moved

            ptemp->m_pparent =pleft;

            for(int i=0; i<ptemp->m_nsize; i++){

                if (ptemp->m_ptr[i]){

                   ptemp->m_ptr[i]->m_pparent = ptemp;

                }

            }

        }

        pright->m_ptr[0] =pright->m_ptr[1];

        pleft->m_nsize++;

        PreMove(pright,0);

    }

    else{

        Merge(pleft, pparent, pright,0);

    }

}

template<typename Type> bool BTree<Type>::Remove(const Type item){

    Triple<Type> result = this->Search(item);

    if(!result.m_ntag){

        return0;

    }

    BTreeNode<Type> *pdel,*pparent, *pmin;

    intn = result.m_nfind;

    pdel = result.m_pfind;

    if(pdel->m_ptr[n+1] != NULL){  //change into delete leafnode

        pmin = pdel->m_ptr[n+1];

        pparent = pdel;

        while(pmin != NULL){

            pparent = pmin;

            pmin =pmin->m_ptr[0];

        }

        pdel->m_pkey[n] =pparent->m_pkey[0];

        pdel = pparent;

        n = 0;

    }

    PreMove(pdel, n); //delete the node

    intmin = (this->m_nMaxSize + 1) / 2;

    while(pdel->m_nsize < min-1){  //if it is not a BTree, then adjust

        n = 0;

        pparent = pdel->m_pparent;

        if(NULL == pparent)

        {

            return1;

        }

        while(n<= pparent->m_nsize && pparent->m_ptr[n]!=pdel){

            n++;

        }

        if(!n){

            RightAdjust(pdel,pparent, min, n); //adjust with the parent and theright child tree

        }

        else{

            LeftAdjust(pdel,pparent, min, n); //adjust with the parent and theleft child tree

        }

        pdel = pparent;

        if(pdel == m_proot){

            break;

        }

    }

    if(!m_proot->m_nsize){         //the root is merged

        pdel = m_proot->m_ptr[0];

        deletem_proot;

        m_proot = pdel;

        m_proot->m_pparent =NULL;

        for(int i=0; i<m_proot->m_nsize; i++){

            if(m_proot->m_ptr[i]){

               m_proot->m_ptr[i]->m_pparent = m_proot;

            }

        }

    }

    return1;

}

template<typename Type> void BTree<Type>::Print(BTreeNode<Type>*start, int n){

    if(NULL == start){

        return;

    }

    if(start->m_ptr[0]){

        Print(start->m_ptr[0],n+1);    //printthe first child tree

    }

    else{

        for(int j=0; j<n; j++){

            cout << "     ";

        }

        cout << "NULL" << endl;

    }

    for(int i=0; i<start->m_nsize; i++){   //print the ortherchild tree

        for(int j=0; j<n; j++){

            cout << "     ";

        }

        cout <<start->m_pkey[i] << "--->"<<endl;

        if(start->m_ptr[i+1]){

           Print(start->m_ptr[i+1], n+1);

        }

        else{

            for(int j=0; j<n; j++){

                cout << "     ";

            }

            cout << "NULL" << endl;

        }

    }

}

template<typename Type> void BTree<Type>::Print(){

    Print(m_proot);

}

template<typename Type> int BTree<Type>::Size(BTreeNode<Type>*root){

    if(NULL == root){

        return0;

    }

    intsize=root->m_nsize;

    for(int i=0; i<=root->m_nsize; i++){

        if(root->m_ptr[i]){

            size += this->Size(root->m_ptr[i]);

        }

    }

    returnsize;

}

template<typename Type> int BTree<Type>::Size(){

    returnthis->Size(this->m_proot);

}

template<typename Type>BTreeNode<Type>* BTree<Type>::GetParent(constType item){

    Triple<Type> result = this->Search(item);

    returnresult.m_pfind->m_pparent;

}

#include <iostream>

#include <cstdlib>

using namespace std;

#include "BTree.h"

int main(){

    BTree<int> btree(3);

    intinit[]={1,3,5,7,4,2,8,0,6,9,29,13,25,11,32,55,34,22,76,45

       ,14,26,33,88,87,92,44,54,23,12,21,99,19,27,57,18,72,124,158,234

   ,187,218,382,122,111,222,333,872,123};

    for(int i=0; i<49; i++){

        btree.Insert(init[i]);

    }

    btree.Print();

    cout << endl << endl<< endl;

    Triple<int> result = btree.Search(13);

    cout << result.m_pfind->GetKey(result.m_nfind)<< endl;

    cout << endl << endl<< endl;

    for(int i=0; i<49; i++){

        btree.Remove(init[i]);

        btree.Print();

        cout << endl <<endl << endl;

    }

    return0;

}