多路平衡树(BTree)的C++实现

  B树是一种多路平衡树,我根据《算法导论》中的算法描述实现了C++版本的BTree。关于BTree的各种属性看这里吧,还有别人的实现版本,看这里。我记得书中并没有给出删除的算法,这个部分我是根据书中的描述自己实现的。完成后自己进行过简单的测试,好像没有什么问题。总共是两个文件BTree.h和Test.cpp,BTree的实现在BTree.h文件中。Test.cpp是测试案例。具体代码如下:

  1 #ifndef __BTREE_H__
  2 #define  __BTREE_H__
  3 
  4 #include <iostream>
  5 
  6 typedef struct _tagBTreeNode
  7 {
  8     int key_count;
  9     int* key;
 10     _tagBTreeNode** child;
 11     bool leaf;
 12 }BTreeNode, *PBTreeNode;
 13 
 14 class BTree
 15 {
 16 public:
 17     BTree();
 18     ~BTree();
 19 
 20     bool Insert(int key);
 21     bool Delete(int key);
 22     void Display(){Print(root);};
 23 
 24 private:
 25     BTreeNode* Search(PBTreeNode pNode, int key);
 26     PBTreeNode AllocateNode();    
 27     void SplitChild(PBTreeNode pParent, int index, PBTreeNode pChild);
 28     PBTreeNode UnionChild(PBTreeNode pParent, PBTreeNode pCLeft, PBTreeNode pCRight, int index);
 29     void InsertNonfull(PBTreeNode pNode, int key);
 30     int Max(PBTreeNode pNode);
 31     int Min(PBTreeNode pNode);
 32     bool DeleteNonHalf(PBTreeNode pNode, int key);
 33     void DellocateNode(PBTreeNode pNode);
 34     void DeleteTree(PBTreeNode pNode);
 35     void Print(PBTreeNode pNode);
 36 private:
 37     PBTreeNode root;
 38     int t;//btree's degree
 39 };
 40 
 41 BTree::BTree() : root(NULL), t(4)
 42 {
 43 };
 44 
 45 BTree::~BTree()
 46 {
 47     DeleteTree(root);
 48     delete root;
 49 };
 50 
 51 PBTreeNode BTree::AllocateNode()
 52 {
 53     PBTreeNode pTemp = new BTreeNode;
 54     pTemp->key = new int[2 * t];
 55     pTemp->child = new PBTreeNode[2 * t + 1];
 56 
 57     for(int i = 0; i < 2 * t ; i++)
 58     {
 59         pTemp->key[i] = 0;
 60         pTemp->child[i] = NULL;
 61     }
 62     pTemp->child[2 * t] = NULL;
 63 
 64     return pTemp;
 65 }
 66 
 67 PBTreeNode BTree::Search(PBTreeNode pNode, int key)
 68 {
 69     int i = 1;
 70     while (i <= pNode->key_count && key > pNode->key[i])
 71         i++;
 72 
 73     if (i < pNode->key_count && key == pNode->key[i])
 74         return pNode->child[i];
 75 
 76     if (pNode->leaf)
 77         return NULL;
 78     else
 79         return Search(pNode->child[i], key);
 80 }
 81 
 82 bool BTree::Insert(int key)
 83 {
 84     PBTreeNode r = root;
 85     if(r == NULL)
 86     {
 87         r = AllocateNode();
 88         r->leaf = true;
 89         r->key_count = 0;
 90 
 91         root = r;
 92     }
 93 
 94     if (r !=NULL && r->key_count == (2 * t - 1))
 95     {
 96         PBTreeNode s = AllocateNode();
 97         root = s;
 98         s->leaf = false;
 99         s->key_count = 0;
100         s->child[1] = r;
101         SplitChild(s, 1, r);
102         InsertNonfull(s, key);
103     }
104     else
105     {
106         InsertNonfull(r, key);
107     }
108 
109     return true;
110 }
111 
112 void BTree::SplitChild(PBTreeNode pParent, int index, PBTreeNode pChild)
113 {
114     PBTreeNode pChildEx = AllocateNode();
115     pChildEx->leaf = pChild->leaf;
116     pChildEx->key_count = t - 1;
117 
118     for(int j = 1; j < t; j++)
119         pChildEx->key[j] = pChild->key[j + t];
120 
121     if(!pChild->leaf)
122         for(int j = 1; j <= t; j++)
123             pChildEx->child[j] = pChild->child[j + t];
124 
125     pChild->key_count = t - 1;
126 
127     for(int j = pParent->key_count + 1; j > index; j--)
128         pParent->child[j + 1] = pParent->child[j];
129     pParent->child[index + 1] = pChildEx;
130 
131     for(int j = pParent->key_count; j >= index; j--)
132         pParent->key[j + 1] = pParent->key[j];
133     pParent->key[index] = pChild->key[t];
134     pParent->key_count++;
135 }
136 
137 void BTree::InsertNonfull(PBTreeNode pNode, int key)
138 {
139     int i = pNode->key_count;
140 
141     if(pNode->leaf)
142     {
143         while(i >= 1 && key < pNode->key[i])
144         {
145             pNode->key[i + 1] = pNode->key[i];
146             i--;
147         }
148 
149         pNode->key[i + 1] = key;
150         pNode->key_count++;
151     }
152     else
153     {
154         while(i >= 1 && key < pNode->key[i])
155             i--;
156         i++;
157 
158         if(pNode->child[i]->key_count == (2 * t - 1))
159         {
160             SplitChild(pNode, i, pNode->child[i]);
161 
162             if(key > pNode->key[i])
163                 i++;
164         }
165 
166         InsertNonfull(pNode->child[i], key);
167     }
168 }
169 
170 bool BTree::Delete(int key)
171 {
172     return DeleteNonHalf(root, key);
173 }
174 
175 bool BTree::DeleteNonHalf(PBTreeNode pNode, int key)
176 {
177     int i = 1;
178 
179     while(i <= pNode->key_count && key > pNode->key[i])
180         i++;
181 
182     if(pNode->leaf)//case 1
183     {
184         if(i <= pNode->key_count && key == pNode->key[i])
185         {
186             for(int j = i; j < pNode->key_count; j++)
187                 pNode->key[j] = pNode->key[j + 1];
188             pNode->key_count--;
189 
190             return true;
191         }
192         else
193         {
194             return false;//没有找到要删除的关键字
195         }
196     }
197 
198     if (i <= pNode->key_count && key == pNode->key[i])//case 2
199     {
200         if (pNode->child[i]->key_count >= t)//case a
201         {
202             key = Max(pNode->child[i]);
203             pNode->key[i] = key;
204 
205             return DeleteNonHalf(pNode->child[i], key);
206         }
207         else if(pNode->child[i + 1]->key_count >= t)//case b
208         {
209             key = Min(pNode->child[i + 1]);
210             pNode->key[i] = key;
211 
212             return DeleteNonHalf(pNode->child[i + 1], key);
213         }
214         else//case c
215         {
216             PBTreeNode pChild = UnionChild(pNode, pNode->child[i], pNode->child[i + 1], i);
217 
218             return DeleteNonHalf(pChild, key);
219         }
220     }
221     else if(pNode->child[i]->key_count == t - 1)//case 3
222     {
223         if ( i > 1 && pNode->child[i - 1]->key_count >= t)//a_left
224         {
225             PBTreeNode pMidNode = pNode->child[i];
226             PBTreeNode pPreNode = pNode->child[i - 1];
227 
228             int nPreNodeKeyCount = pPreNode->key_count;
229 
230             for (int j = pMidNode->key_count + 1; j > 1; j--)
231                 pMidNode->key[j] = pMidNode->key[j - 1];
232             pMidNode->key[1] = pNode->key[i - 1];
233 
234             for (int j = pMidNode->key_count + 2; j > 1; j--)
235                 pMidNode->child[j] = pMidNode->child[j - 1];
236             pMidNode->child[1] = pPreNode->child[nPreNodeKeyCount + 1];
237             pMidNode->key_count++;
238 
239             pNode->key[i - 1] = pPreNode->key[nPreNodeKeyCount];
240 
241             pPreNode->key[nPreNodeKeyCount] = 0;
242             pPreNode->key[nPreNodeKeyCount + 1] = NULL;
243             pPreNode->key_count--;
244 
245             return DeleteNonHalf(pMidNode, key);
246         }
247         else if( i <= pNode->key_count && pNode->child[i + 1]->key_count >= t)//a_right
248         {
249             PBTreeNode pMidNode = pNode->child[i];
250             PBTreeNode pNextNode = pNode->child[i + 1];
251 
252             int nNextNodeKeyCount = pNextNode->key_count;
253             int nMidNodeKeyCount = pMidNode->key_count;
254             
255             pMidNode->key[nMidNodeKeyCount + 1] = pNode->key[i];
256             pMidNode->child[nMidNodeKeyCount + 2] = pNextNode->child[1];
257             pMidNode->key_count++;
258 
259             pNode->key[i] = pNextNode->key[1];
260 
261             for( int j = 1; j < nNextNodeKeyCount; j++)
262                 pNextNode->key[j] = pNextNode->key[j + 1];
263             for( int j = 1; j <= nNextNodeKeyCount; j++)
264                 pNextNode->child[j] = pNextNode->child[j + 1];
265             pNextNode->key_count--;
266             
267             return DeleteNonHalf(pMidNode, key);
268         }
269         else//b
270         {
271             if (i > pNode->key_count)//当i指向最后一个关键字的时候,合并的时候要往前移动一步
272                 i--;
273 
274             PBTreeNode pChild = UnionChild(pNode, pNode->child[i], pNode->child[i + 1], i);
275 
276             return DeleteNonHalf(pChild, key);
277         }
278     }
279 
280     return DeleteNonHalf(pNode->child[i], key);
281 }
282 
283 PBTreeNode BTree::UnionChild(PBTreeNode pParent, PBTreeNode pCLeft, PBTreeNode pCRight, int index)
284 {
285     for(int i = 1; i < t; i++)
286         pCLeft->key[t + i] = pCRight->key[i];
287     pCLeft->key[t] = pParent->key[index];
288 
289     for(int i = 1; i <= t; i++)
290         pCLeft->child[t + i] = pCRight->child[i];
291     pCLeft->key_count = 2 * t - 1;
292 
293     for(int i = index; i < pParent->key_count; i++)
294         pParent->key[i] = pParent->key[i + 1];
295 
296     for(int i = index + 1; i <= pParent->key_count; i++)
297         pParent->child[i] = pParent->child[i + 1];
298     pParent->key_count--;
299 
300     DellocateNode(pCRight);
301 
302     if (pParent->key_count == 0)
303     {
304         DellocateNode(root);
305         root = pCLeft;
306     }
307 
308     return pCLeft;
309 }
310 
311 void BTree::DellocateNode(PBTreeNode pNode)
312 {
313     delete[] pNode->key;
314     delete[] pNode->child;
315     delete pNode;
316 }
317 
318 int BTree::Max(PBTreeNode pNode)
319 {
320     while (!pNode->leaf)
321     {
322         pNode = pNode->child[pNode->key_count + 1];
323     }
324 
325     return pNode->key[pNode->key_count];
326 }
327 
328 int BTree::Min(PBTreeNode pNode)
329 {
330     while (!pNode->leaf)
331     {
332         pNode = pNode->child[1];
333     }
334 
335     return pNode->key[1];
336 }
337 
338 void BTree::DeleteTree(PBTreeNode pNode)//最后的根元素没有被删除 但是根里的关键字数组和孩子指针数组已经删除
339 {
340     if(pNode->leaf)
341     {
342         delete[] pNode->key;
343         delete[] pNode->child;
344     }
345     else
346     {
347         for(int i = 1; i <= pNode->key_count + 1; i++)
348         {
349             DeleteTree(pNode->child[i]);
350             delete pNode->child[i];
351         }
352 
353         delete[] pNode->key;
354         delete[] pNode->child;
355     }
356 }
357 
358 void BTree::Print(PBTreeNode pNode)
359 {
360     if(pNode->leaf)
361     {
362         std::cout << "leaf key_count = " << pNode->key_count << " key list :" ;
363 
364         for(int i = 1; i <= pNode->key_count;  i++)
365         {
366             //std::cout << " i = " << i << std::endl;
367             std::cout << pNode->key[i] << " , ";
368         }
369 
370         std::cout << std::endl;
371     }
372     else
373     {
374         for(int i = 1; i <= pNode->key_count + 1; i++)
375             Print(pNode->child[i]);
376 
377         std::cout << "inner node key_count " << pNode->key_count << " key list :" ;
378 
379         for(int i = 1; i <= pNode->key_count; i++)
380         {
381             //std::cout << " i = " << i << std::endl;
382             std::cout << pNode->key[i] << " , ";
383         }
384         std::cout << std::endl;
385     }
386 }
387 
388 #endif // __BTREE_H__

  测试案例代码如下:

 1 #include "BTree.h"
 2 #include <ctime>
 3 #include <iostream>
 4 #include <cstdlib>
 5 #include <set>
 6 
 7 int main()
 8 {
 9     BTree b;
10 
11     for(int i = 50; i > 1; i--)
12     {
13         int x = rand() % 10000;
14         b.Insert(x);
15     }
16 
17     b.Display();
18 }

  编译方式g++ -o Test Test.cpp,执行过程如下:

 1 [kiven@localhost Test]$ g++ -o Test Test.cpp
 2 [kiven@localhost Test]$ ./Test
 3 leaf key_count = 3 key list :27 , 59 , 492 ,
 4 leaf key_count = 4 key list :886 , 1393 , 1421 , 1530 ,
 5 leaf key_count = 6 key list :2567 , 2777 , 2862 , 3058 , 3069 , 3135 ,
 6 leaf key_count = 4 key list :3784 , 3926 , 3929 , 4022 ,
 7 inner node key_count 3 key list :540 , 2362 , 3426 ,
 8 leaf key_count = 6 key list :4324 , 4421 , 4919 , 5011 , 5123 , 5198 ,
 9 leaf key_count = 7 key list :5368 , 5386 , 5736 , 5782 , 6229 , 6429 , 6649 ,
10 leaf key_count = 3 key list :7373 , 7763 , 7793 ,
11 leaf key_count = 5 key list :8167 , 8315 , 8335 , 8456 , 8537 ,
12 leaf key_count = 3 key list :9172 , 9383 , 9802 ,
13 inner node key_count 4 key list :5211 , 6915 , 8042 , 8690 ,
14 inner node key_count 1 key list :4067 ,
15 [kiven@localhost Test]$

 

posted @ 2013-03-04 14:17  kiven.li  阅读(1697)  评论(0编辑  收藏  举报