BTreeNode.h
template<typename Type> class BTree; template<typename Type> class BTreeNode{ public: friend BTree<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; } } void Destroy(BTreeNode<Type> *root); ~BTreeNode(){ if (m_nMaxSize){ delete[] m_pkey; for (int i=0; i<=m_nMaxSize; i++){ m_ptr[i] = NULL; } } } bool IsFull(){ return m_nsize == m_nMaxSize; } Type GetKey(int i){ if (this){ return this->m_pkey[i]; } return -1; } private: int m_nsize; int m_nMaxSize; //the Max Size of key Type *m_pkey; BTreeNode<Type> *m_pparent; BTreeNode<Type> **m_ptr; static const Type m_Infinity = 10000; }; template<typename Type> struct Triple{ BTreeNode<Type> *m_pfind; int m_nfind; bool m_ntag; }; template<typename Type> void BTreeNode<Type>::Destroy(BTreeNode<Type> *root){ if (NULL == root){ return; } for (int i=0; i<root->m_nsize; i++){ Destroy(root->m_ptr[i]); } delete root; }
BTree.h
#include "BTreeNode.h" template<typename Type> class BTree{ public: BTree(int size): m_nMaxSize(size), m_proot(NULL){} ~BTree(); Triple<Type> Search(const Type item); int Size(); int Size(BTreeNode<Type> *root); bool Insert(const Type item); //insert item bool Remove(const Type item); //delete item void Print(); //print the BTree BTreeNode<Type> *GetParent(const Type item); private: //insert the pright and item to pinsert in the nth place; void InsertKey(BTreeNode<Type> *pinsert, int n, const Type item, BTreeNode<Type> *pright); void PreMove(BTreeNode<Type> *root, int n); //move ahead //merge the child tree void Merge(BTreeNode<Type> *pleft, BTreeNode<Type> *pparent, BTreeNode<Type> *pright, int n); //adjust with the parent and the left child tree void LeftAdjust(BTreeNode<Type> *pright, BTreeNode<Type> *pparent, int min, int n); //adjust with the parent and the left child tree void RightAdjust(BTreeNode<Type> *pleft, BTreeNode<Type> *pparent, int min, int n); void Print(BTreeNode<Type> *start, int n = 0); private: BTreeNode<Type> *m_proot; const int m_nMaxSize; }; template<typename Type> BTree<Type>::~BTree(){ m_proot->Destroy(m_proot); } template<typename Type> Triple<Type> BTree<Type>::Search(const Type item){ Triple<Type> result; BTreeNode<Type> *pmove = m_proot, *parent = NULL; int i = 0; while (pmove){ i = -1; while (item > pmove->m_pkey[++i]); //find the suit position if (pmove->m_pkey[i] == item){ result.m_pfind = pmove; result.m_nfind = i; result.m_ntag = 1; return result; } parent = pmove; pmove = pmove->m_ptr[i]; //find in the child tree } result.m_pfind = parent; result.m_nfind = i; result.m_ntag = 0; return result; } template<typename Type> void BTree<Type>::InsertKey(BTreeNode<Type> *pinsert, int n, const Type item, BTreeNode<Type> *pright){ pinsert->m_nsize++; for (int i=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; return 1; } Triple<Type> find = this->Search(item); //search the position if (find.m_ntag){ cerr << "The item is exist!" << endl; return 0; } BTreeNode<Type> *pinsert = find.m_pfind, *newnode; BTreeNode<Type> *pright = NULL, *pparent; Type key = item; int n = find.m_nfind; while (1){ if (pinsert->m_nsize < pinsert->m_nMaxSize-1){ //There is some space InsertKey(pinsert, n, key, pright); return 1; } int m = (pinsert->m_nsize + 1) / 2; //get the middle item InsertKey(pinsert, n, key, pright); //insert first, then break up newnode = new BTreeNode<Type>(this->m_nMaxSize);//create the newnode for break up //break up 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 the parent 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 the parent 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]; } } } } //break up 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 { //create new 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; return 1; } } } 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){ //change thd 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; delete pright; PreMove(pparent, n); // this->Print(); } template<typename Type> void BTree<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){ //change the 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> void BTree<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){ //change the 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){ return 0; } BTreeNode<Type> *pdel, *pparent, *pmin; int n = 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 int min = (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) { return 1; } while (n<= pparent->m_nsize && pparent->m_ptr[n]!=pdel){ n++; } if (!n){ RightAdjust(pdel, pparent, min, n); //adjust with the parent and the right child tree } else { LeftAdjust(pdel, pparent, min, n); //adjust with the parent and the left child tree } pdel = pparent; if (pdel == m_proot){ break; } } if (!m_proot->m_nsize){ //the root is merged pdel = m_proot->m_ptr[0]; delete m_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; } } } return 1; } 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); //print the 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 orther child 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){ return 0; } int size=root->m_nsize; for (int i=0; i<=root->m_nsize; i++){ if (root->m_ptr[i]){ size += this->Size(root->m_ptr[i]); } } return size; } template<typename Type> int BTree<Type>::Size(){ return this->Size(this->m_proot); } template<typename Type> BTreeNode<Type>* BTree<Type>::GetParent(const Type item){ Triple<Type> result = this->Search(item); return result.m_pfind->m_pparent; }
test.cpp
#include <iostream> #include <cstdlib> using namespace std; #include "BTree.h" int main(){ BTree<int> btree(3); int init[]={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; } return 0; }