B+树练习
1 #ifndef BTREE_H 2 #define BTREE_H 3 4 #include 5 #include 6 const int maxValue=10000; 7 8 ///////////////////////////////////////////////// 9 //BTreeNodeB树的结点的定义 10 ///////////////////////////////////////////////// 11 template 12 struct BTreeNode 13 { 14 int n; //结点中关键码的个数 15 BTreeNode* parent; //当前结点的父结点的指针 16 17 T* key; //m+1个元素存放关键码,其中key[0]和key[m]没有用 18 BTreeNode** //子树指针的结点数组(一共有m棵子树),m+1个元素 19 subTree; //最后一个元素subTree[m]在插入溢出的时候使用 20 int** recptr; //每个索引项中指向数据区相应记录起始地址的指针数组 21 BTreeNode(int m) //构造函数 22 { 23 n=0; //关键码个数初始化为0 24 parent=NULL; //父结点指针初始化为空 25 key=new T[m+1]; //开辟关键码数组的空间 26 subTree=new //开辟子树的指针数组的内存空间 27 BTreeNode*[m+1]; //从p0,p1,p2,...p(m-1)共m棵子树 28 for(int i=0;i<=m;i++) 29 subTree中 30 { 31 for(int i=1;i<=n;i++) //寻找插入关键码的位置 32 { 33 if(x 34 key中 35 subTree[j+1]=subTree[j]; 36 subTree<<" "; 37 }; 38 }; 39 /////////////////////////////////BTree定义结束 40 41 ///////////////////////////////////////////////// 42 //Triple结构 返回搜索结果用的三元组 43 ///////////////////////////////////////////////// 44 template 45 struct Triple 46 { 47 BTreeNode* r; //结点指针 48 int i; //关键码在当前结点中的序号 49 int tag; //tag=0:搜索成功,tag=1:搜索失败 50 }; 51 ////////////////////////////////Triple结构结束 52 53 ///////////////////////////////////////////////// 54 //BTree B树的定义; 55 //m阶B树的根至少有两个子树, 56 //其他的结点至少应该有int(m/2)+1个子树 57 //所有的失败结点都在一个层次上 58 ///////////////////////////////////////////////// 59 template 60 class BTree 61 { 62 private: 63 BTreeNode* root; //树根结点指针 64 int m; //即B树的阶数 65 public: 66 BTree(int x) //空构造函数,构造一棵空x路的搜索树 67 {root=NULL;m=x;}; 68 BTree(int x,BTreeNode* r) 69 {root=r;m=x;}; //用指定的树根来初始化当前的m路搜索树 70 void Insert( //在树指定父结点的情况下插入一个结点 71 BTreeNode* pa, //指定要出入的位置的父结点 72 BTreeNode* subTree, //要插入的结点的指针 73 int i); //表示插入到pa的第i个子树的位置 74 75 Triple //搜索指定关键码x对应的结点 76 Search(const T& x); 77 void RootFirst( //递归:以先根的方式遍历当前的搜索树 78 BTreeNode* subTree); 79 void RootFirst() //调用上面的递归函数 80 {RootFirst(root);}; 81 bool Insert(const T& x); //B树的插入操作 82 void Display( 83 BTreeNode* p,int i); //递归:以缩进的格式显示当前的B树 84 void Display() //调用上面的递归函数 85 {cout<<"*****当前B树的缩进结构显示*****:"< 86 Display(root,1);}; 87 }; 88 //////////////////////////////////////B树声明结束 89 90 ///////////////////////////////////////////////// 91 //RootFirst()公有成员函数 92 //以先根的方式递归遍历当前B树 93 ///////////////////////////////////////////////// 94 template 95 void BTree::RootFirst(BTreeNode* st) 96 { 97 if(st!=NULL) 98 { 99 int n=st->n; 100 cout<<"当前结点有"< 101 <<"个关键码:"< 102 for(int k=1;k<=n;k++) //输出当前结点的所有的关键码 103 cout<key[k]<<" "; 104 cout<< 105 for(int i=0;i<=n;i++) //递归输出所有的子树 106 RootFirst(st->subTree==x) //如果找到 107 { 108 result.r=ptr; //当前查找驻留的结点指针 109 result.i=i; //查找成功的关键码 110 result.tag=1; //是否查找成功 111 return result; 112 }; 113 if(ptr->key; //从失配的关键码左边的子树继续查找 114 }; 115 /*如果查找失败*/ 116 result.r=pre; 117 result.i=i; //可以在i-1和i之间进行插入 118 result.tag=0; //查找失败 119 120 return result; 121 }; 122 /////////////////////////////////Search()函数结束 123 124 ///////////////////////////////////////////////// 125 //Insert()公有成员函数 B树的插入操作 126 //把指定的关键码插入到B树中,使得仍然满足B树的要求 127 //首先对B树进行搜索,如果关键码已经存在则插入失败, 128 //否则执行插入,并按B树要求进行调整 129 //一般来说,执行插入的肯定是在叶子结点上进行 130 //但是如果查找成功的话,可能在非叶子结点上就结束了 131 ///////////////////////////////////////////////// 132 template 133 bool BTree::Insert(const T& x) 134 { 135 /*如果当前的B树是空的,就新建之*/ 136 if(root==NULL) //如果当前的B树是空的 137 { 138 root=new BTreeNode(m); //新建一个结点 139 root->Insert(x,NULL); //把关键码插入到key[]数组第一个位置 140 return true; 141 }; 142 143 /*如果当前的B树不空,就搜索该树*/ 144 Triple Tp; //查找结果三元组 145 Tp=Search(x); 146 int IsIn=Tp.tag; 147 if(IsIn==1) //关键码已经存在 148 { 149 cout<<"关键码已存在!"< 150 return false; //插入失败 151 }; 152 153 /*插入关键码直到结点关键码不溢出为止*/ 154 BTreeNode* ptr=Tp.r; //查找失败而驻留的结点 155 int loc=Tp.i-1; //在k[loc]后进行插入 156 int pkey=x; 157 BTreeNode* p=NULL; //随关键一起要插入的右子树的根结点 158 do 159 { 160 ptr->Insert(pkey,p); //把关键码和相关的新分裂的右结点插入当前结点 161 if(ptr->n>m-1) //如果关键码溢出,则需要进行调整 162 { 163 /*以下处理结点的分裂*/ 164 int k=ptr->key[m/2+1]; //提取出要上提的关键码 165 BTreeNode* right //建立分裂后右边的结点 166 =new BTreeNode(m); 167 right->n=ptr->n-m/2-1; //右结点的关键码个数 168 for(int i=m/2+2;i<=ptr->n;i++) 169 right->key //把右半边的关键码复制进入右结点 170 =ptr->key 171 =ptr->subTree=k; //插入新关键码 172 newp->subTree[0] //新关键码左边的子树 173 =ptr; 174 newp->subTree[1] //新关键码右边的子树 175 =right; 176 newp->n=1; //新关键码个数为1 177 ptr->parent=newp; //设置父结点指针 178 right->parent=newp; 179 root=newp; 180 return true; //插入成功并结束 181 } 182 else //如果有父结点存在 183 ptr=ptr->parent; //把上提的关键码继续插入父结点 184 } 185 else //不溢出则插入成功 186 return true; 187 }while(ptr!=NULL); 188 189 return true; 190 }; 191 /////////////////////////Insert()公有成员函数结束 192 193 ///////////////////////////////////////////////// 194 //Display()公有成员函数 195 //递归:显示当前B树的缩进格式 196 ///////////////////////////////////////////////// 197 template 198 void BTree::Display(BTreeNode* p,int i) 199 { 200 if(p!=NULL) 201 { 202 for(int j=0;j 203 cout<<" "; //控制缩进的格数 204 cout<<"当前结点是:关键码个数"<n<<" " 205 <<"关键码的内容是"; 206 for(int k=1;k<=p->n;k++)//显示当前结点所有关键码 207 cout<key[k]<<" "; 208 cout< 209 for(k=0;k<=p->n;k++) //递归显示子树,递归向后缩进 210 Display(p->subTree[k],i+5); 211 }; 212 }; 213 ////////////////////////////////Display()函数结束 214 215 #endif 216 217 #include"BTree.h" 218 219 ///////////////////////////////////////////////// 220 //main()函数 测试B树的程序 221 ///////////////////////////////////////////////// 222 int main() 223 { 224 BTree BT(3); 225 BT.Insert(53); //依此在B树中插入关键码 226 BT.Insert(75); 227 BT.Insert(139); 228 BT.Insert(49); 229 BT.Insert(145); 230 BT.Insert(36); 231 BT.Insert(101); 232 BT.Insert(150); 233 BT.Insert(170); 234 BT.Insert(25); 235 BT.Insert(13); 236 237 BT.Display(); //显示当前B树的内容 238 return 0; 239 };