SLikeNet 0.1.3

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DS_BPlusTree.h
Go to the documentation of this file.
1 /*
2 * Original work: Copyright (c) 2014, Oculus VR, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * RakNet License.txt file in the licenses directory of this source tree. An additional grant
7 * of patent rights can be found in the RakNet Patents.txt file in the same directory.
8 *
9 *
10 * Modified work: Copyright (c) 2016-2018, SLikeSoft UG (haftungsbeschränkt)
11 *
12 * This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
13 * license found in the license.txt file in the root directory of this source tree.
14 */
15
18
19
20 #ifndef __B_PLUS_TREE_CPP
21 #define __B_PLUS_TREE_CPP
22
23 #include "DS_MemoryPool.h"
24 #include "DS_Queue.h"
25 #include <stdio.h>
26 #include "Export.h"
27
28 // Java
29 // http://www.seanster.com/BplusTree/BplusTree.html
30
31 // Overview
32 // http://babbage.clarku.edu/~achou/cs160/B+Trees/B+Trees.htm
33
34 // Deletion
35 // http://dbpubs.stanford.edu:8090/pub/1995-19
36
37 #ifdef _MSC_VER
38 #pragma warning( push )
39 #endif
40
41 #include "memoryoverride.h"
42
45 namespace DataStructures
46 {
49 template <class KeyType, class DataType, int order>
50 struct RAK_DLL_EXPORT Page
51 {
52 // We use the same data structure for both leaf and index nodes.
53 // It uses a little more memory for index nodes but reduces
54 // memory fragmentation, allocations, and deallocations.
55 bool isLeaf;
56
57 // Used for both leaf and index nodes.
58 // For a leaf it means the number of elements in data
59 // For an index it means the number of keys and is one less than the number of children pointers.
60 int size;
61
62 // Used for both leaf and index nodes.
63 KeyType keys[order];
64
65 // Used only for leaf nodes. Data is the actual data, while next is the pointer to the next leaf (for B+)
66 DataType data[order];
67 Page<KeyType, DataType, order> *next;
68 Page<KeyType, DataType, order> *previous;
69
70 // Used only for index nodes. Pointers to the children of this node.
71 Page *children[order+1];
72 };
73
76 template <class KeyType, class DataType, int order>
77 class RAK_DLL_EXPORT BPlusTree
78 {
79 public:
80 struct ReturnAction
81 {
82 KeyType key1;
83 KeyType key2;
84 enum
85 {
86 NO_ACTION,
87 REPLACE_KEY1_WITH_KEY2,
88 PUSH_KEY_TO_PARENT,
89 SET_BRANCH_KEY,
90 } action; // 0=none, 1=replace key1 with key2
91 };
92
93 BPlusTree();
94 ~BPlusTree();
95 void SetPoolPageSize(int size); // Set the page size for the memory pool. Optionsl
96 bool Get(const KeyType key, DataType &out) const;
97 bool Delete(const KeyType key);
98 bool Delete(const KeyType key, DataType &out);
99 bool Insert(const KeyType key, const DataType &data);
100 void Clear(void);
101 unsigned Size(void) const;
102 bool IsEmpty(void) const;
103 Page<KeyType, DataType, order> *GetListHead(void) const;
104 DataType GetDataHead(void) const;
105 void PrintLeaves(void);
106 void ForEachLeaf(void (*func)(Page<KeyType, DataType, order> * leaf, int index));
107 void ForEachData(void (*func)(DataType input, int index));
108 void PrintGraph(void);
109 protected:
110 void ValidateTreeRecursive(Page<KeyType, DataType, order> *cur);
111 void DeleteFromPageAtIndex(const int index, Page<KeyType, DataType, order> *cur);
112 static void PrintLeaf(Page<KeyType, DataType, order> * leaf, int index);
113 void FreePages(void);
114 bool GetIndexOf(const KeyType key, Page<KeyType, DataType, order> *page, int *out) const;
115 void ShiftKeysLeft(Page<KeyType, DataType, order> *cur);
116 bool CanRotateLeft(Page<KeyType, DataType, order> *cur, int childIndex);
117 bool CanRotateRight(Page<KeyType, DataType, order> *cur, int childIndex);
118 void RotateRight(Page<KeyType, DataType, order> *cur, int childIndex, ReturnAction *returnAction);
119 void RotateLeft(Page<KeyType, DataType, order> *cur, int childIndex, ReturnAction *returnAction);
120 Page<KeyType, DataType, order>* InsertIntoNode(const KeyType key, const DataType &childData, int insertionIndex, Page<KeyType, DataType, order> *nodeData, Page<KeyType, DataType, order> *cur, ReturnAction* returnAction);
121 Page<KeyType, DataType, order>* InsertBranchDown(const KeyType key, const DataType &data,Page<KeyType, DataType, order> *cur, ReturnAction* returnAction, bool *success);
122 Page<KeyType, DataType, order>* GetLeafFromKey(const KeyType key) const;
123 bool FindDeleteRebalance(const KeyType key, Page<KeyType, DataType, order> *cur, bool *underflow, KeyType rightRootKey, ReturnAction *returnAction, DataType &out);
124 bool FixUnderflow(int branchIndex, Page<KeyType, DataType, order> *cur, KeyType rightRootKey, ReturnAction *returnAction);
125 void ShiftNodeLeft(Page<KeyType, DataType, order> *cur);
126 void ShiftNodeRight(Page<KeyType, DataType, order> *cur);
127
128 MemoryPool<Page<KeyType, DataType, order> > pagePool;
129 Page<KeyType, DataType, order> *root, *leftmostLeaf;
130 };
131
132 template<class KeyType, class DataType, int order>
133 BPlusTree<KeyType, DataType, order>::BPlusTree ()
134 {
135 RakAssert(order>1);
136 root=0;
137 leftmostLeaf=0;
138 }
139 template<class KeyType, class DataType, int order>
140 BPlusTree<KeyType, DataType, order>::~BPlusTree ()
141 {
142 Clear();
143 }
144 template<class KeyType, class DataType, int order>
145 void BPlusTree<KeyType, DataType, order>::SetPoolPageSize(int size)
146 {
147 pagePool.SetPageSize(size);
148 }
149 template<class KeyType, class DataType, int order>
150 bool BPlusTree<KeyType, DataType, order>::Get(const KeyType key, DataType &out) const
151 {
152 if (root==0)
153 return false;
154
155 Page<KeyType, DataType, order>* leaf = GetLeafFromKey(key);
156 int childIndex;
157
158 if (GetIndexOf(key, leaf, &childIndex))
159 {
160 out=leaf->data[childIndex];
161 return true;
162 }
163 return false;
164 }
165 template<class KeyType, class DataType, int order>
166 void BPlusTree<KeyType, DataType, order>::DeleteFromPageAtIndex(const int index, Page<KeyType, DataType, order> *cur)
167 {
168 int i;
169 for (i=index; i < cur->size-1; i++)
170 cur->keys[i]=cur->keys[i+1];
171 if (cur->isLeaf)
172 {
173 for (i=index; i < cur->size-1; i++)
174 cur->data[i]=cur->data[i+1];
175 }
176 else
177 {
178 for (i=index; i < cur->size-1; i++)
179 cur->children[i+1]=cur->children[i+2];
180 }
181 cur->size--;
182 }
183 template<class KeyType, class DataType, int order>
184 bool BPlusTree<KeyType, DataType, order>::Delete(const KeyType key)
185 {
186 DataType temp;
187 return Delete(key, temp);
188 }
189 template<class KeyType, class DataType, int order>
190 bool BPlusTree<KeyType, DataType, order>::Delete(const KeyType key, DataType &out)
191 {
192 if (root==0)
193 return false;
194
195 ReturnAction returnAction;
196 returnAction.action=ReturnAction::NO_ACTION;
197 int childIndex;
198 bool underflow=false;
199 if (root==leftmostLeaf)
200 {
201 if (GetIndexOf(key, root, &childIndex)==false)
202 return false;
203 out=root->data[childIndex];
204 DeleteFromPageAtIndex(childIndex,root);
205 if (root->size==0)
206 {
207 pagePool.Release(root, _FILE_AND_LINE_);
208 root=0;
209 leftmostLeaf=0;
210 }
211 return true;
212 }
213 else if (FindDeleteRebalance(key, root, &underflow,root->keys[0], &returnAction, out)==false)
214 return false;
215
216 // RakAssert(returnAction.action==ReturnAction::NO_ACTION);
217
218 if (underflow && root->size==0)
219 {
220 // Move the root down.
221 Page<KeyType, DataType, order> *oldRoot=root;
222 root=root->children[0];
223 pagePool.Release(oldRoot, _FILE_AND_LINE_);
224 // memset(oldRoot,0,sizeof(root));
225 }
226
227 return true;
228 }
229 template<class KeyType, class DataType, int order>
230 bool BPlusTree<KeyType, DataType, order>::FindDeleteRebalance(const KeyType key, Page<KeyType, DataType, order> *cur, bool *underflow, KeyType rightRootKey, ReturnAction *returnAction, DataType &out)
231 {
232 // Get index of child to follow.
233 int branchIndex, childIndex;
234 if (GetIndexOf(key, cur, &childIndex))
235 branchIndex=childIndex+1;
236 else
237 branchIndex=childIndex;
238
239 // If child is not a leaf, call recursively
240 if (cur->children[branchIndex]->isLeaf==false)
241 {
242 if (branchIndex<cur->size)
243 rightRootKey=cur->keys[branchIndex]; // Shift right to left
244 else
245 rightRootKey=cur->keys[branchIndex-1]; // Shift center to left
246
247 if (FindDeleteRebalance(key, cur->children[branchIndex], underflow, rightRootKey, returnAction, out)==false)
248 return false;
249
250 // Call again in case the root key changed
251 if (branchIndex<cur->size)
252 rightRootKey=cur->keys[branchIndex]; // Shift right to left
253 else
254 rightRootKey=cur->keys[branchIndex-1]; // Shift center to left
255
256 if (returnAction->action==ReturnAction::SET_BRANCH_KEY && branchIndex!=childIndex)
257 {
258 returnAction->action=ReturnAction::NO_ACTION;
259 cur->keys[childIndex]=returnAction->key1;
260
261 if (branchIndex<cur->size)
262 rightRootKey=cur->keys[branchIndex]; // Shift right to left
263 else
264 rightRootKey=cur->keys[branchIndex-1]; // Shift center to left
265 }
266 }
267 else
268 {
269 // If child is a leaf, get the index of the key. If the item is not found, cancel delete.
270 if (GetIndexOf(key, cur->children[branchIndex], &childIndex)==false)
271 return false;
272
273 // Delete:
274 // Remove childIndex from the child at branchIndex
275 out=cur->children[branchIndex]->data[childIndex];
276 DeleteFromPageAtIndex(childIndex, cur->children[branchIndex]);
277
278 if (childIndex==0)
279 {
280 if (branchIndex>0)
281 cur->keys[branchIndex-1]=cur->children[branchIndex]->keys[0];
282
283 if (branchIndex==0)
284 {
285 returnAction->action=ReturnAction::SET_BRANCH_KEY;
286 returnAction->key1=cur->children[0]->keys[0];
287 }
288 }
289
290 if (cur->children[branchIndex]->size < order/2)
291 *underflow=true;
292 else
293 *underflow=false;
294 }
295
296 // Fix underflow:
297 if (*underflow)
298 {
299 *underflow=FixUnderflow(branchIndex, cur, rightRootKey, returnAction);
300 }
301
302 return true;
303 }
304 template<class KeyType, class DataType, int order>
305 bool BPlusTree<KeyType, DataType, order>::FixUnderflow(int branchIndex, Page<KeyType, DataType, order> *cur, KeyType rightRootKey, ReturnAction *returnAction)
306 {
307 // Borrow from a neighbor that has excess.
308 Page<KeyType, DataType, order> *source;
309 Page<KeyType, DataType, order> *dest;
310
311 if (branchIndex>0 && cur->children[branchIndex-1]->size > order/2)
312 {
313 dest=cur->children[branchIndex];
314 source=cur->children[branchIndex-1];
315
316 // Left has excess
317 ShiftNodeRight(dest);
318 if (dest->isLeaf)
319 {
320 dest->keys[0]=source->keys[source->size-1];
321 dest->data[0]=source->data[source->size-1];
322 }
323 else
324 {
325 dest->children[0]=source->children[source->size];
326 dest->keys[0]=cur->keys[branchIndex-1];
327 }
328 // Update the parent key for the child (middle)
329 cur->keys[branchIndex-1]=source->keys[source->size-1];
330 source->size--;
331
332 // if (branchIndex==0)
333 // {
334 // returnAction->action=ReturnAction::SET_BRANCH_KEY;
335 // returnAction->key1=dest->keys[0];
336 // }
337
338 // No underflow
339 return false;
340 }
341 else if (branchIndex<cur->size && cur->children[branchIndex+1]->size > order/2)
342 {
343 dest=cur->children[branchIndex];
344 source=cur->children[branchIndex+1];
345
346 // Right has excess
347 if (dest->isLeaf)
348 {
349 dest->keys[dest->size]=source->keys[0];
350 dest->data[dest->size]=source->data[0];
351
352 // The first key in the leaf after shifting is the parent key for the right branch
353 cur->keys[branchIndex]=source->keys[1];
354
355 #ifdef _MSC_VER
356 #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
357 #endif
358 if (order<=3 && dest->size==0)
359 {
360 if (branchIndex==0)
361 {
362 returnAction->action=ReturnAction::SET_BRANCH_KEY;
363 returnAction->key1=dest->keys[0];
364 }
365 else
366 cur->keys[branchIndex-1]=cur->children[branchIndex]->keys[0];
367 }
368 }
369 else
370 {
371 if (returnAction->action==ReturnAction::NO_ACTION)
372 {
373 returnAction->action=ReturnAction::SET_BRANCH_KEY;
374 returnAction->key1=dest->keys[0];
375 }
376
377 dest->keys[dest->size]=rightRootKey;
378 dest->children[dest->size+1]=source->children[0];
379
380 // The shifted off key is the leftmost key for a node
381 cur->keys[branchIndex]=source->keys[0];
382 }
383
384
385 dest->size++;
386 ShiftNodeLeft(source);
387
388 //cur->keys[branchIndex]=source->keys[0];
389
390 // returnAction->action=ReturnAction::SET_BRANCH_KEY;
391 // returnAction->key1=dest->keys[dest->size-1];
392
393 // No underflow
394 return false;
395 }
396 else
397 {
398 int sourceIndex;
399
400 // If no neighbors have excess, merge two branches.
401 //
402 // To merge two leaves, just copy the data and keys over.
403 //
404 // To merge two branches, copy the pointers and keys over, using rightRootKey as the key for the extra pointer
405 if (branchIndex<cur->size)
406 {
407 // Merge right child to current child and delete right child.
408 dest=cur->children[branchIndex];
409 source=cur->children[branchIndex+1];
410 }
411 else
412 {
413 // Move current child to left and delete current child
414 dest=cur->children[branchIndex-1];
415 source=cur->children[branchIndex];
416 }
417
418 // Merge
419 if (dest->isLeaf)
420 {
421 for (sourceIndex=0; sourceIndex<source->size; sourceIndex++)
422 {
423 dest->keys[dest->size]=source->keys[sourceIndex];
424 dest->data[dest->size++]=source->data[sourceIndex];
425 }
426 }
427 else
428 {
429 // We want the tree root key of the source, not the current.
430 dest->keys[dest->size]=rightRootKey;
431 dest->children[dest->size++ + 1]=source->children[0];
432 for (sourceIndex=0; sourceIndex<source->size; sourceIndex++)
433 {
434 dest->keys[dest->size]=source->keys[sourceIndex];
435 dest->children[dest->size++ + 1]=source->children[sourceIndex + 1];
436 }
437 }
438
439 #ifdef _MSC_VER
440 #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
441 #endif
442 if (order<=3 && branchIndex>0 && cur->children[branchIndex]->isLeaf) // With order==2 it is possible to delete data[0], which is not possible with higher orders.
443 cur->keys[branchIndex-1]=cur->children[branchIndex]->keys[0];
444
445 if (branchIndex<cur->size)
446 {
447 // Update the parent key, removing the source (right)
448 DeleteFromPageAtIndex(branchIndex, cur);
449 }
450 else
451 {
452 if (branchIndex>0)
453 {
454 // Update parent key, removing the source (current)
455 DeleteFromPageAtIndex(branchIndex-1, cur);
456 }
457 }
458
459 if (branchIndex==0 && dest->isLeaf)
460 {
461 returnAction->action=ReturnAction::SET_BRANCH_KEY;
462 returnAction->key1=dest->keys[0];
463 }
464
465 if (source==leftmostLeaf)
466 leftmostLeaf=source->next;
467
468 if (source->isLeaf)
469 {
470 if (source->previous)
471 source->previous->next=source->next;
472 if (source->next)
473 source->next->previous=source->previous;
474 }
475
476 // Free the source node
477 pagePool.Release(source, _FILE_AND_LINE_);
478 // memset(source,0,sizeof(root));
479
480 // Return underflow or not of parent.
481 return cur->size < order/2;
482 }
483 }
484 template<class KeyType, class DataType, int order>
485 void BPlusTree<KeyType, DataType, order>::ShiftNodeRight(Page<KeyType, DataType, order> *cur)
486 {
487 int i;
488 for (i=cur->size; i>0; i--)
489 cur->keys[i]=cur->keys[i-1];
490 if (cur->isLeaf)
491 {
492 for (i=cur->size; i>0; i--)
493 cur->data[i]=cur->data[i-1];
494 }
495 else
496 {
497 for (i=cur->size+1; i>0; i--)
498 cur->children[i]=cur->children[i-1];
499 }
500
501 cur->size++;
502 }
503 template<class KeyType, class DataType, int order>
504 void BPlusTree<KeyType, DataType, order>::ShiftNodeLeft(Page<KeyType, DataType, order> *cur)
505 {
506 int i;
507 for (i=0; i < cur->size-1; i++)
508 cur->keys[i]=cur->keys[i+1];
509 if (cur->isLeaf)
510 {
511 for (i=0; i < cur->size; i++)
512 cur->data[i]=cur->data[i+1];
513 }
514 else
515 {
516 for (i=0; i < cur->size; i++)
517 cur->children[i]=cur->children[i+1];
518 }
519 cur->size--;
520 }
521 template<class KeyType, class DataType, int order>
522 Page<KeyType, DataType, order>* BPlusTree<KeyType, DataType, order>::InsertIntoNode(const KeyType key, const DataType &leafData, int insertionIndex, Page<KeyType, DataType, order> *nodeData, Page<KeyType, DataType, order> *cur, ReturnAction* returnAction)
523 {
524 int i;
525 if (cur->size < order)
526 {
527 for (i=cur->size; i > insertionIndex; i--)
528 cur->keys[i]=cur->keys[i-1];
529 if (cur->isLeaf)
530 {
531 for (i=cur->size; i > insertionIndex; i--)
532 cur->data[i]=cur->data[i-1];
533 }
534 else
535 {
536 for (i=cur->size+1; i > insertionIndex+1; i--)
537 cur->children[i]=cur->children[i-1];
538 }
539 cur->keys[insertionIndex]=key;
540 if (cur->isLeaf)
541 cur->data[insertionIndex]=leafData;
542 else
543 cur->children[insertionIndex+1]=nodeData;
544
545 cur->size++;
546 }
547 else
548 {
549 Page<KeyType, DataType, order>* newPage = pagePool.Allocate( _FILE_AND_LINE_ );
550 newPage->isLeaf=cur->isLeaf;
551 if (cur->isLeaf)
552 {
553 newPage->next=cur->next;
554 if (cur->next)
555 cur->next->previous=newPage;
556 newPage->previous=cur;
557 cur->next=newPage;
558 }
559
560 int destIndex, sourceIndex;
561
562 if (insertionIndex>=(order+1)/2)
563 {
564 destIndex=0;
565 sourceIndex=order/2;
566
567 for (; sourceIndex < insertionIndex; sourceIndex++, destIndex++)
568 {
569 newPage->keys[destIndex]=cur->keys[sourceIndex];
570 }
571 newPage->keys[destIndex++]=key;
572 for (; sourceIndex < order; sourceIndex++, destIndex++)
573 {
574 newPage->keys[destIndex]=cur->keys[sourceIndex];
575 }
576
577 destIndex=0;
578 sourceIndex=order/2;
579 if (cur->isLeaf)
580 {
581 for (; sourceIndex < insertionIndex; sourceIndex++, destIndex++)
582 {
583 newPage->data[destIndex]=cur->data[sourceIndex];
584 }
585 newPage->data[destIndex++]=leafData;
586 for (; sourceIndex < order; sourceIndex++, destIndex++)
587 {
588 newPage->data[destIndex]=cur->data[sourceIndex];
589 }
590 }
591 else
592 {
593
594 for (; sourceIndex < insertionIndex; sourceIndex++, destIndex++)
595 {
596 newPage->children[destIndex]=cur->children[sourceIndex+1];
597 }
598 newPage->children[destIndex++]=nodeData;
599
600 // sourceIndex+1 is sort of a hack but it works - because there is one extra child than keys
601 // skip past the last child for cur
602 for (; sourceIndex+1 < cur->size+1; sourceIndex++, destIndex++)
603 {
604 newPage->children[destIndex]=cur->children[sourceIndex+1];
605 }
606
607 // the first key is the middle key. Remove it from the page and push it to the parent
608 returnAction->action=ReturnAction::PUSH_KEY_TO_PARENT;
609 returnAction->key1=newPage->keys[0];
610 for (int j=0; j < destIndex-1; j++)
611 newPage->keys[j]=newPage->keys[j+1];
612
613 }
614 cur->size=order/2;
615 }
616 else
617 {
618 destIndex=0;
619 sourceIndex=(order+1)/2-1;
620 for (; sourceIndex < order; sourceIndex++, destIndex++)
621 newPage->keys[destIndex]=cur->keys[sourceIndex];
622 destIndex=0;
623 if (cur->isLeaf)
624 {
625 sourceIndex=(order+1)/2-1;
626 for (; sourceIndex < order; sourceIndex++, destIndex++)
627 newPage->data[destIndex]=cur->data[sourceIndex];
628 }
629 else
630 {
631 sourceIndex=(order+1)/2;
632 for (; sourceIndex < order+1; sourceIndex++, destIndex++)
633 newPage->children[destIndex]=cur->children[sourceIndex];
634
635 // the first key is the middle key. Remove it from the page and push it to the parent
636 returnAction->action=ReturnAction::PUSH_KEY_TO_PARENT;
637 returnAction->key1=newPage->keys[0];
638 for (int j=0; j < destIndex-1; j++)
639 newPage->keys[j]=newPage->keys[j+1];
640 }
641 cur->size=(order+1)/2-1;
642 if (cur->size)
643 {
644 bool b = GetIndexOf(key, cur, &insertionIndex);
645 (void) b;
646 RakAssert(b==false);
647 }
648 else
649 insertionIndex=0;
650 InsertIntoNode(key, leafData, insertionIndex, nodeData, cur, returnAction);
651 }
652
653 newPage->size=destIndex;
654
655 return newPage;
656 }
657
658 return 0;
659 }
660
661 template<class KeyType, class DataType, int order>
662 bool BPlusTree<KeyType, DataType, order>::CanRotateLeft(Page<KeyType, DataType, order> *cur, int childIndex)
663 {
664 return childIndex>0 && cur->children[childIndex-1]->size<order;
665 }
666
667 template<class KeyType, class DataType, int order>
668 void BPlusTree<KeyType, DataType, order>::RotateLeft(Page<KeyType, DataType, order> *cur, int childIndex, ReturnAction *returnAction)
669 {
670 Page<KeyType, DataType, order> *dest = cur->children[childIndex-1];
671 Page<KeyType, DataType, order> *source = cur->children[childIndex];
672 returnAction->key1=source->keys[0];
673 dest->keys[dest->size]=source->keys[0];
674 dest->data[dest->size]=source->data[0];
675 dest->size++;
676 for (int i=0; i < source->size-1; i++)
677 {
678 source->keys[i]=source->keys[i+1];
679 source->data[i]=source->data[i+1];
680 }
681 source->size--;
682 cur->keys[childIndex-1]=source->keys[0];
683 returnAction->key2=source->keys[0];
684 }
685
686 template<class KeyType, class DataType, int order>
687 bool BPlusTree<KeyType, DataType, order>::CanRotateRight(Page<KeyType, DataType, order> *cur, int childIndex)
688 {
689 return childIndex < cur->size && cur->children[childIndex+1]->size<order;
690 }
691
692 template<class KeyType, class DataType, int order>
693 void BPlusTree<KeyType, DataType, order>::RotateRight(Page<KeyType, DataType, order> *cur, int childIndex, ReturnAction *returnAction)
694 {
695 Page<KeyType, DataType, order> *dest = cur->children[childIndex+1];
696 Page<KeyType, DataType, order> *source = cur->children[childIndex];
697 returnAction->key1=dest->keys[0];
698 for (int i= dest->size; i > 0; i--)
699 {
700 dest->keys[i]=dest->keys[i-1];
701 dest->data[i]=dest->data[i-1];
702 }
703 dest->keys[0]=source->keys[source->size-1];
704 dest->data[0]=source->data[source->size-1];
705 dest->size++;
706 source->size--;
707
708 cur->keys[childIndex]=dest->keys[0];
709 returnAction->key2=dest->keys[0];
710 }
711 template<class KeyType, class DataType, int order>
712 Page<KeyType, DataType, order>* BPlusTree<KeyType, DataType, order>::GetLeafFromKey(const KeyType key) const
713 {
714 Page<KeyType, DataType, order>* cur = root;
715 int childIndex;
716 while (cur->isLeaf==false)
717 {
718 // When searching, if we match the exact key we go down the pointer after that index
719 if (GetIndexOf(key, cur, &childIndex))
720 childIndex++;
721 cur = cur->children[childIndex];
722 }
723 return cur;
724 }
725
726 template<class KeyType, class DataType, int order>
727 Page<KeyType, DataType, order>* BPlusTree<KeyType, DataType, order>::InsertBranchDown(const KeyType key, const DataType &data,Page<KeyType, DataType, order> *cur, ReturnAction *returnAction, bool *success)
728 {
729 int childIndex;
730 int branchIndex;
731 if (GetIndexOf(key, cur, &childIndex))
732 branchIndex=childIndex+1;
733 else
734 branchIndex=childIndex;
735 Page<KeyType, DataType, order>* newPage;
736 if (cur->isLeaf==false)
737 {
738 if (cur->children[branchIndex]->isLeaf==true && cur->children[branchIndex]->size==order)
739 {
740 if (branchIndex==childIndex+1)
741 {
742 *success=false;
743 return 0; // Already exists
744 }
745
746 if (CanRotateLeft(cur, branchIndex))
747 {
748 returnAction->action=ReturnAction::REPLACE_KEY1_WITH_KEY2;
749 if (key > cur->children[branchIndex]->keys[0])
750 {
751 RotateLeft(cur, branchIndex, returnAction);
752
753 int insertionIndex;
754 GetIndexOf(key, cur->children[branchIndex], &insertionIndex);
755 InsertIntoNode(key, data, insertionIndex, 0, cur->children[branchIndex], 0);
756 }
757 else
758 {
759 // Move head element to left and replace it with key,data
760 Page<KeyType, DataType, order>* dest=cur->children[branchIndex-1];
761 Page<KeyType, DataType, order>* source=cur->children[branchIndex];
762 returnAction->key1=source->keys[0];
763 returnAction->key2=key;
764 dest->keys[dest->size]=source->keys[0];
765 dest->data[dest->size]=source->data[0];
766 dest->size++;
767 source->keys[0]=key;
768 source->data[0]=data;
769 }
770 cur->keys[branchIndex-1]=cur->children[branchIndex]->keys[0];
771
772 return 0;
773 }
774 else if (CanRotateRight(cur, branchIndex))
775 {
776 returnAction->action=ReturnAction::REPLACE_KEY1_WITH_KEY2;
777
778 if (key < cur->children[branchIndex]->keys[cur->children[branchIndex]->size-1])
779 {
780 RotateRight(cur, branchIndex, returnAction);
781
782 int insertionIndex;
783 GetIndexOf(key, cur->children[branchIndex], &insertionIndex);
784 InsertIntoNode(key, data, insertionIndex, 0, cur->children[branchIndex], 0);
785
786 }
787 else
788 {
789 // Insert to the head of the right leaf instead and change our key
790 returnAction->key1=cur->children[branchIndex+1]->keys[0];
791 InsertIntoNode(key, data, 0, 0, cur->children[branchIndex+1], 0);
792 returnAction->key2=key;
793 }
794 cur->keys[branchIndex]=cur->children[branchIndex+1]->keys[0];
795 return 0;
796 }
797 }
798
799 newPage=InsertBranchDown(key,data,cur->children[branchIndex], returnAction, success);
800 if (returnAction->action==ReturnAction::REPLACE_KEY1_WITH_KEY2)
801 {
802 if (branchIndex>0 && cur->keys[branchIndex-1]==returnAction->key1)
803 cur->keys[branchIndex-1]=returnAction->key2;
804 }
805 if (newPage)
806 {
807 if (newPage->isLeaf==false)
808 {
809 RakAssert(returnAction->action==ReturnAction::PUSH_KEY_TO_PARENT);
810 newPage->size--;
811 return InsertIntoNode(returnAction->key1, data, branchIndex, newPage, cur, returnAction);
812 }
813 else
814 {
815 return InsertIntoNode(newPage->keys[0], data, branchIndex, newPage, cur, returnAction);
816 }
817 }
818 }
819 else
820 {
821 if (branchIndex==childIndex+1)
822 {
823 *success=false;
824 return 0; // Already exists
825 }
826 else
827 {
828 return InsertIntoNode(key, data, branchIndex, 0, cur, returnAction);
829 }
830 }
831
832 return 0;
833 }
834 template<class KeyType, class DataType, int order>
835 bool BPlusTree<KeyType, DataType, order>::Insert(const KeyType key, const DataType &data)
836 {
837 if (root==0)
838 {
839 // Allocate root and make root a leaf
840 root = pagePool.Allocate( _FILE_AND_LINE_ );
841 root->isLeaf=true;
842 leftmostLeaf=root;
843 root->size=1;
844 root->keys[0]=key;
845 root->data[0]=data;
846 root->next=0;
847 root->previous=0;
848 }
849 else
850 {
851 bool success=true;
852 ReturnAction returnAction;
853 returnAction.action=ReturnAction::NO_ACTION;
854 Page<KeyType, DataType, order>* newPage = InsertBranchDown(key, data, root, &returnAction, &success);
855 if (success==false)
856 return false;
857 if (newPage)
858 {
859 KeyType newKey;
860 if (newPage->isLeaf==false)
861 {
862 // One key is pushed up through the stack. I store that at keys[0] but it has to be removed for the page to be correct
863 RakAssert(returnAction.action==ReturnAction::PUSH_KEY_TO_PARENT);
864 newKey=returnAction.key1;
865 newPage->size--;
866 }
867 else
868 newKey = newPage->keys[0];
869 // propagate the root
870 Page<KeyType, DataType, order>* newRoot = pagePool.Allocate( _FILE_AND_LINE_ );
871 newRoot->isLeaf=false;
872 newRoot->size=1;
873 newRoot->keys[0]=newKey;
874 newRoot->children[0]=root;
875 newRoot->children[1]=newPage;
876 root=newRoot;
877 }
878 }
879
880 return true;
881 }
882 template<class KeyType, class DataType, int order>
883 void BPlusTree<KeyType, DataType, order>::ShiftKeysLeft(Page<KeyType, DataType, order> *cur)
884 {
885 int i;
886 for (i=0; i < cur->size; i++)
887 cur->keys[i]=cur->keys[i+1];
888 }
889 template<class KeyType, class DataType, int order>
890 void BPlusTree<KeyType, DataType, order>::Clear(void)
891 {
892 if (root)
893 {
894 FreePages();
895 leftmostLeaf=0;
896 root=0;
897 }
898 pagePool.Clear(_FILE_AND_LINE_);
899 }
900 template<class KeyType, class DataType, int order>
901 unsigned BPlusTree<KeyType, DataType, order>::Size(void) const
902 {
903 unsigned int count=0;
904 DataStructures::Page<KeyType, DataType, order> *cur = GetListHead();
905 while (cur)
906 {
907 count+=cur->size;
908 cur=cur->next;
909 }
910 return count;
911 }
912 template<class KeyType, class DataType, int order>
913 bool BPlusTree<KeyType, DataType, order>::IsEmpty(void) const
914 {
915 return root==0;
916 }
917 template<class KeyType, class DataType, int order>
918 bool BPlusTree<KeyType, DataType, order>::GetIndexOf(const KeyType key, Page<KeyType, DataType, order> *page, int *out) const
919 {
920 RakAssert(page->size>0);
921 int index, upperBound, lowerBound;
922 upperBound=page->size-1;
923 lowerBound=0;
924 index = page->size/2;
925
926 for(;;)
927 {
928 if (key==page->keys[index])
929 {
930 *out=index;
931 return true;
932 }
933 else if (key<page->keys[index])
934 upperBound=index-1;
935 else
936 lowerBound=index+1;
937
938 index=lowerBound+(upperBound-lowerBound)/2;
939
940 if (lowerBound>upperBound)
941 {
942 *out=lowerBound;
943 return false; // No match
944 }
945 }
946 }
947 template<class KeyType, class DataType, int order>
948 void BPlusTree<KeyType, DataType, order>::FreePages(void)
949 {
950 DataStructures::Queue<DataStructures::Page<KeyType, DataType, order> *> queue;
951 DataStructures::Page<KeyType, DataType, order> *ptr;
952 int i;
953 queue.Push(root, _FILE_AND_LINE_ );
954 while (queue.Size())
955 {
956 ptr=queue.Pop();
957 if (ptr->isLeaf==false)
958 {
959 for (i=0; i < ptr->size+1; i++)
960 queue.Push(ptr->children[i], _FILE_AND_LINE_ );
961 }
962 pagePool.Release(ptr, _FILE_AND_LINE_);
963 // memset(ptr,0,sizeof(root));
964 };
965 }
966 template<class KeyType, class DataType, int order>
967 Page<KeyType, DataType, order> *BPlusTree<KeyType, DataType, order>::GetListHead(void) const
968 {
969 return leftmostLeaf;
970 }
971 template<class KeyType, class DataType, int order>
972 DataType BPlusTree<KeyType, DataType, order>::GetDataHead(void) const
973 {
974 return leftmostLeaf->data[0];
975 }
976 template<class KeyType, class DataType, int order>
977 void BPlusTree<KeyType, DataType, order>::ForEachLeaf(void (*func)(Page<KeyType, DataType, order> * leaf, int index))
978 {
979 int count=0;
980 DataStructures::Page<KeyType, DataType, order> *cur = GetListHead();
981 while (cur)
982 {
983 func(cur, count++);
984 cur=cur->next;
985 }
986 }
987 template<class KeyType, class DataType, int order>
988 void BPlusTree<KeyType, DataType, order>::ForEachData(void (*func)(DataType input, int index))
989 {
990 int count=0,i;
991 DataStructures::Page<KeyType, DataType, order> *cur = GetListHead();
992 while (cur)
993 {
994 for (i=0; i < cur->size; i++)
995 func(cur->data[i], count++);
996 cur=cur->next;
997 }
998 }
999 template<class KeyType, class DataType, int order>
1000 void BPlusTree<KeyType, DataType, order>::PrintLeaf(Page<KeyType, DataType, order> * leaf, int index)
1001 {
1002 int i;
1003 RAKNET_DEBUG_PRINTF("%i] SELF=%p\n", index+1, leaf);
1004 for (i=0; i < leaf->size; i++)
1005 // #med - need to adjust printf-format specified based on the actual datatype
1006 RAKNET_DEBUG_PRINTF(" %i. %p\n", i+1, leaf->data[i]);
1007 }
1008 template<class KeyType, class DataType, int order>
1009 void BPlusTree<KeyType, DataType, order>::PrintLeaves(void)
1010 {
1011 ForEachLeaf(PrintLeaf);
1012 }
1013
1014 template<class KeyType, class DataType, int order>
1015 void BPlusTree<KeyType, DataType, order>::ValidateTreeRecursive(Page<KeyType, DataType, order> *cur)
1016 {
1017 RakAssert(cur==root || cur->size>=order/2);
1018
1019 if (cur->children[0]->isLeaf)
1020 {
1021 RakAssert(cur->children[0]->keys[0] < cur->keys[0]);
1022 for (int i=0; i < cur->size; i++)
1023 {
1024 RakAssert(cur->children[i+1]->keys[0]==cur->keys[i]);
1025 }
1026 }
1027 else
1028 {
1029 for (int i=0; i < cur->size+1; i++)
1030 ValidateTreeRecursive(cur->children[i]);
1031 }
1032 }
1033
1034 template<class KeyType, class DataType, int order>
1035 void BPlusTree<KeyType, DataType, order>::PrintGraph(void)
1036 {
1037 DataStructures::Queue<DataStructures::Page<KeyType, DataType, order> *> queue;
1038 queue.Push(root,_FILE_AND_LINE_);
1039 queue.Push(0,_FILE_AND_LINE_);
1040 DataStructures::Page<KeyType, DataType, order> *ptr;
1041 int i,j;
1042 if (root)
1043 {
1044 RAKNET_DEBUG_PRINTF("%p(", root);
1045 for (i=0; i < root->size; i++)
1046 {
1047 RAKNET_DEBUG_PRINTF("%i ", root->keys[i]);
1048 }
1049 RAKNET_DEBUG_PRINTF(") ");
1050 RAKNET_DEBUG_PRINTF("\n");
1051 }
1052 while (queue.Size())
1053 {
1054 ptr=queue.Pop();
1055 if (ptr==0)
1056 RAKNET_DEBUG_PRINTF("\n");
1057 else if (ptr->isLeaf==false)
1058 {
1059 for (i=0; i < ptr->size+1; i++)
1060 {
1061 RAKNET_DEBUG_PRINTF("%p(", ptr->children[i]);
1062 //RAKNET_DEBUG_PRINTF("(", ptr->children[i]);
1063 for (j=0; j < ptr->children[i]->size; j++)
1064 RAKNET_DEBUG_PRINTF("%i ", ptr->children[i]->keys[j]);
1065 RAKNET_DEBUG_PRINTF(") ");
1066 queue.Push(ptr->children[i],_FILE_AND_LINE_);
1067 }
1068 queue.Push(0,_FILE_AND_LINE_);
1069 RAKNET_DEBUG_PRINTF(" -- ");
1070 }
1071 }
1072 RAKNET_DEBUG_PRINTF("\n");
1073 }
1074 }
1075 #ifdef _MSC_VER
1076 #pragma warning( pop )
1077 #endif
1078
1079 #endif
1080
1081 // Code to test this hellish data structure.
1082 /*
1083 #include "DS_BPlusTree.h"
1084 #include <stdio.h>
1085
1086 // Handle underflow on root. If there is only one item left then I can go downwards.
1087 // Make sure I keep the leftmost pointer valid by traversing it
1088 // When I free a leaf, be sure to adjust the pointers around it.
1089
1090 #include "Rand.h"
1091
1092 void main(void)
1093 {
1094 DataStructures::BPlusTree<int, int, 16> btree;
1095 DataStructures::List<int> haveList, removedList;
1096 int temp;
1097 int i, j, index;
1098 int testSize;
1099 bool b;
1100
1101 for (testSize=0; testSize < 514; testSize++)
1102 {
1103 RAKNET_DEBUG_PRINTF("TestSize=%i\n", testSize);
1104
1105 for (i=0; i < testSize; i++)
1106 haveList.Insert(i);
1107
1108 for (i=0; i < testSize; i++)
1109 {
1110 index=i+randomMT()%(testSize-i);
1111 temp=haveList[index];
1112 haveList[index]=haveList[i];
1113 haveList[i]=temp;
1114 }
1115
1116 for (i=0; i<testSize; i++)
1117 {
1118 btree.Insert(haveList[i], haveList[i]);
1119 btree.ValidateTree();
1120 }
1121
1122 for (i=0; i < testSize; i++)
1123 {
1124 index=i+randomMT()%(testSize-i);
1125 temp=haveList[index];
1126 haveList[index]=haveList[i];
1127 haveList[i]=temp;
1128 }
1129 for (i=0; i<testSize; i++)
1130 {
1131 btree.Delete(haveList[0]); // Asserts on 8th call. Fails on going to remove 8 (7th call)
1132 removedList.Insert(haveList[0]);
1133 haveList.RemoveAtIndex(0);
1134 for (j=0; j < removedList.Size(); j++)
1135 {
1136 b=btree.Get(removedList[j], temp);
1137 RakAssert(b==false);
1138 }
1139 for (j=0; j < haveList.Size(); j++)
1140 {
1141 b=btree.Get(haveList[j], temp);
1142 RakAssert(b==true);
1143 RakAssert(haveList[j]==temp);
1144 }
1145 RakAssert(btree.Size()==haveList.Size());
1146 btree.ValidateTree();
1147 }
1148 btree.Clear(_FILE_AND_LINE_);
1149 removedList.Clear(_FILE_AND_LINE_);
1150 haveList.Clear(_FILE_AND_LINE_);
1151 }
1152
1153 RAKNET_DEBUG_PRINTF("Done. %i\n", btree.Size());
1154 char ch[256];
1155 Gets(ch, sizeof(ch));
1156 }
1157 */