C++模板实现B+树
来源:互联网 发布:jade软件 编辑:程序博客网 时间:2024/06/03 10:38
B+ 树是一种树数据结构,是一个n叉排序树,每个节点通常有多个孩子,一棵B+树包含根节点、内部节点和叶子节点。根节点可能是一个叶子节点,也可能是一个包含两个或两个以上孩子节点的节点。
B+ 树通常用于数据库和操作系统的文件系统中。NTFS, ReiserFS, NSS, XFS, JFS, ReFS 和BFS等文件系统都在使用B+树作为元数据索引。B+ 树的特点是能够保持数据稳定有序,其插入与修改拥有较稳定的对数时间复杂度。B+ 树元素自底向上插入
B+ 树通常用于数据库和操作系统的文件系统中。NTFS, ReiserFS, NSS, XFS, JFS, ReFS 和BFS等文件系统都在使用B+树作为元数据索引。B+ 树的特点是能够保持数据稳定有序,其插入与修改拥有较稳定的对数时间复杂度。B+ 树元素自底向上插入
B+树的定义:B+树是应文件系统所需而出的一种B-树的变型树。一棵m阶的B+树和m阶的B-树的差异在于:
1.有n棵子树的结点中含有n个关键字,每个关键字不保存数据,只用来索引,所有数据都保存在叶子节点。
2.所有的叶子结点中包含了全部关键字的信息,及指向含这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。
3.所有的非终端结点可以看成是索引部分,结点中仅含其子树(根结点)中的最大(或最小)关键字。
通常在B+树上有两个头指针,一个指向根结点,一个指向关键字最小的叶子结点。
3.所有的非终端结点可以看成是索引部分,结点中仅含其子树(根结点)中的最大(或最小)关键字。
通常在B+树上有两个头指针,一个指向根结点,一个指向关键字最小的叶子结点。
下面我们使用模板简单实现B+树:
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;}Main.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;}
阅读全文
1 0
- C++模板实现B+树
- B树C语言实现
- B树的C实现
- B树的C实现
- B树的C实现
- B+树C语言实现
- a^b%c问题 ---模板
- C语言-B树(B-树)的完整实现
- B树的原理与实现(C++)
- [c#]BPlusTreePrototype - B+树的C#实现
- B树基本操作C实现
- 数据结构 B+树c代码实现
- b树的实现(c++)
- HDU5698(排列组合 C(a,b)modP 模板 )
- A^B mod C(快速幂模板)
- C语言实现stack模板
- C语言实现函数模板
- [c++]栈模板的实现
- 【背包专题】C
- pip install
- UVA1658Admiral
- LeetCode.58 Length of Last Word
- [笔记分享] [Android] Android系统概述
- C++模板实现B+树
- HDU
- [js高手之路]构造函数的基本特性与优缺点
- hdu 1558
- netCore2.0 加载DonetTools失败
- 排序算法——优先队列(基于堆得优先队列)
- Linux Ubuntu 16.04 系统上安装mysql
- iOS项目换电脑开发出现的问题:证书、cocoapod、svn
- 位置信息挖掘