Advertisement
Guest User

Btree

a guest
Mar 24th, 2019
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.53 KB | None | 0 0
  1. /**********************************************
  2. * File: BTreeNode.h
  3. * Author: Matthew Morrison
  4. * Email: matt.morrison@nd.edu
  5. *
  6. * Implementation of a Templated C++ Class BTreeNode
  7. *
  8. * Developed from the implementation from CLRS Text
  9. * T. H. et al Cormen, Introduction to algorithms. Cambridge, MA: MIT Press, 2009.
  10. **********************************************/
  11. #ifndef BTREENODE_H
  12. #define BTREENODE_H
  13.  
  14. #include<iostream>
  15.  
  16. // A BTree node
  17. template<class T>
  18. class BTreeNode
  19. {
  20.  
  21. public:
  22. T *keys; // An array of keys
  23. int t; // Minimum degree (defines the range for number of keys)
  24. BTreeNode<T> **childPtrs; // An array of child pointers
  25. int numKeys; // Current number of keys
  26. bool leaf; // Is true when node is leaf. Otherwise false
  27.  
  28. /********************************************
  29. * Function Name : BTreeNode<T>
  30. * Pre-conditions : int _t, bool _leaf
  31. * Post-conditions: none
  32. *
  33. * BTreeNode Constructor
  34. ********************************************/
  35. BTreeNode<T>(int _t, bool _leaf) : t(_t), leaf(_leaf) {
  36.  
  37. // Allocate memory for maximum number of possible keys
  38. // and child pointers
  39. keys = new T[2*t-1];
  40. childPtrs = new BTreeNode<T>* [2*t];
  41.  
  42. // Initialize the number of keys as 0
  43. numKeys = 0;
  44. }
  45.  
  46. /********************************************
  47. * Function Name : traverse
  48. * Pre-conditions : none
  49. * Post-conditions: none
  50. *
  51. * A function to traverse all nodes in a subtree rooted with this node
  52. ********************************************/
  53. void traverse()
  54. {
  55. // There are numKeys keys and numKeys+1 children, travers through numKeys keys
  56. // and first numKeys children
  57. int i;
  58. for (i = 0; i < numKeys; i++)
  59. {
  60. // If this is not leaf, then before printing key[i],
  61. // traverse the subtree rooted with child childPtrs[i].
  62. if (leaf == false)
  63. childPtrs[i]->traverse();
  64. std::cout << " " << keys[i];
  65. }
  66.  
  67. // Print the subtree rooted with last child
  68. if (leaf == false)
  69. childPtrs[i]->traverse();
  70. }
  71.  
  72. /********************************************
  73. * Function Name : search
  74. * Pre-conditions : T key
  75. * Post-conditions: BTreeNode<T>*
  76. *
  77. * A function to search a key in the subtree rooted with this node.
  78. ********************************************/
  79. BTreeNode<T>* search(T key){
  80. // Find the first key greater than or equal to k
  81. int i = 0;
  82. while (i < numKeys && key > keys[i])
  83. i++;
  84.  
  85. // If the found key is equal to k, return this node
  86. if(i < numKeys){
  87. if (keys[i] == key)
  88. return;
  89. }
  90.  
  91. // If the key is not found here and this is a leaf node
  92. if (leaf == true)
  93. return NULL;
  94.  
  95. // Go to the appropriate child
  96. return childPtrs[i]->search(key);
  97. }
  98.  
  99. /********************************************
  100. * Function Name : printFoundNodes
  101. * Pre-conditions : T key, int level
  102. * Post-conditions: void
  103. *
  104. * A function to search a key in the subtree rooted with this node.
  105. * print all nodes at the level
  106. ********************************************/
  107. void printFoundNodes(T key, int level){
  108.  
  109. int iter = 0;
  110. std::cout << "Level " << level << ": ";
  111.  
  112. while(iter < numKeys){
  113.  
  114. //Print the current key
  115. std::cout << keys[iter] << " ";
  116. iter++;
  117. }
  118. std::cout << std::endl;
  119.  
  120. // Find the first key greater than or equal to k
  121. int i = 0;
  122. while (i < numKeys && key > keys[i])
  123. i++;
  124.  
  125. // If the found key is equal to k, return this node
  126. if(i < numKeys){
  127. if (keys[i] == key)
  128. return;
  129. }
  130.  
  131. // If the key is not found here and this is a leaf node
  132. if (leaf == true)
  133. return;
  134.  
  135. // Go to the appropriate child
  136. childPtrs[i]->printFoundNodes(key, level+1);
  137. }
  138.  
  139. /********************************************
  140. * Function Name : insertNonFull
  141. * Pre-conditions : T key
  142. * Post-conditions: none
  143. *
  144. * A utility function to insert a new key in this node
  145. * The assumption is, the node must be non-full when this
  146. * function is called
  147. ********************************************/
  148. void insertNonFull(T key)
  149. {
  150. // Initialize index as index of rightmost element
  151. int i = numKeys-1;
  152.  
  153. // If this is a leaf node
  154. if (leaf == true)
  155. {
  156. // The following loop does two things
  157. // a) Finds the location of new key to be inserted
  158. // b) Moves all greater keys to one place ahead
  159. while (i >= 0 && keys[i] > key)
  160. {
  161. keys[i+1] = keys[i];
  162. i--;
  163. }
  164.  
  165. // Insert the new key at found location
  166. keys[i+1] = key;
  167. numKeys = numKeys+1;
  168. }
  169. else // If this node is not leaf
  170. {
  171. // Find the child which is going to have the new key
  172. while (i >= 0 && keys[i] > key)
  173. i--;
  174.  
  175. // See if the found child is full
  176. if (childPtrs[i+1]->numKeys == 2*t-1)
  177. {
  178. // If the child is full, then split it
  179. splitChild(i+1, childPtrs[i+1]);
  180.  
  181. // After split, the middle key of childPtrs[i] goes up and
  182. // childPtrs[i] is splitted into two. See which of the two
  183. // is going to have the new key
  184. if (keys[i+1] < key)
  185. i++;
  186. }
  187. childPtrs[i+1]->insertNonFull(key);
  188. }
  189. }
  190.  
  191. /********************************************
  192. * Function Name : splitChild
  193. * Pre-conditions : int i, BTreeNode<T> *y
  194. * Post-conditions: none
  195. *
  196. * A utility function to split the child y of this node
  197. * Note that y must be full when this function is called
  198. ********************************************/
  199. void splitChild(int i, BTreeNode<T> *y)
  200. {
  201. // Create a new node which is going to store (t-1) keys
  202. // of y
  203. BTreeNode<T> *z = new BTreeNode<T>(y->t, y->leaf);
  204. z->numKeys = t - 1;
  205.  
  206. // Copy the last (t-1) keys of y to z
  207. for (int j = 0; j < t-1; j++)
  208. z->keys[j] = y->keys[j+t];
  209.  
  210. // Copy the last t children of y to z
  211. if (y->leaf == false)
  212. {
  213. for (int j = 0; j < t; j++)
  214. z->childPtrs[j] = y->childPtrs[j+t];
  215. }
  216.  
  217. // Reduce the number of keys in y
  218. y->numKeys = t - 1;
  219.  
  220. // Since this node is going to have a new child,
  221. // create space of new child
  222. for (int j = numKeys; j >= i+1; j--)
  223. childPtrs[j+1] = childPtrs[j];
  224.  
  225. // Link the new child to this node
  226. childPtrs[i+1] = z;
  227.  
  228. // A key of y will move to this node. Find location of
  229. // new key and move all greater keys one space ahead
  230. for (int j = numKeys-1; j >= i; j--)
  231. keys[j+1] = keys[j];
  232.  
  233. // Copy the middle key of y to this node
  234. keys[i] = y->keys[t-1];
  235.  
  236. // Increment count of keys in this node
  237. numKeys = numKeys + 1;
  238. }
  239.  
  240.  
  241. /********************************************
  242. * Function Name : findKey
  243. * Pre-conditions : T key
  244. * Post-conditions: int
  245. *
  246. * A utility function that returns the index of the first key that is
  247. * greater than or equal to k
  248. ********************************************/
  249. int findKey(T key)
  250. {
  251. int index=0;
  252. while (index < numKeys && keys[index] < key)
  253. ++index;
  254. return index;
  255. }
  256.  
  257. /********************************************
  258. * Function Name : remove
  259. * Pre-conditions : T key
  260. * Post-conditions: none
  261. *
  262. * A function to remove the key k from the sub-tree rooted with this node
  263. ********************************************/
  264. void remove(T key)
  265. {
  266. int index = findKey(key);
  267.  
  268. // The key to be removed is present in this node
  269. if (index < numKeys && keys[index] == key)
  270. {
  271.  
  272. // If the node is a leaf node - removeFromLeaf is called
  273. // Otherwise, removeFromNonLeaf function is called
  274. if (leaf)
  275. removeFromLeaf(index);
  276. else
  277. removeFromNonLeaf(index);
  278. }
  279. else
  280. {
  281.  
  282. // If this node is a leaf node, then the key is not present in tree
  283. if (leaf)
  284. {
  285. std::cout << "The key "<< key <<" is does not exist in the tree\n";
  286. return;
  287. }
  288.  
  289. // The key to be removed is present in the sub-tree rooted with this node
  290. // The flag indicates whether the key is present in the sub-tree rooted
  291. // with the last child of this node
  292. bool flag = ( (index==numKeys)? true : false );
  293.  
  294. // If the child where the key is supposed to exist has less that t keys,
  295. // we fill that child
  296. if (childPtrs[index]->numKeys < t)
  297. fill(index);
  298.  
  299. // If the last child has been merged, it must have merged with the previous
  300. // child and so we recurse on the (index-1)th child. Else, we recurse on the
  301. // (index)th child which now has atleast t keys
  302. if (flag && index > numKeys)
  303. childPtrs[index-1]->remove(key);
  304. else
  305. childPtrs[index]->remove(key);
  306. }
  307. return;
  308. }
  309.  
  310. /********************************************
  311. * Function Name : removeFromLeaf
  312. * Pre-conditions : int index
  313. * Post-conditions: none
  314. *
  315. * A function to remove the index-th key from this node - which is a leaf node
  316. ********************************************/
  317. void removeFromLeaf (int index)
  318. {
  319.  
  320. // Move all the keys after the index-th pos one place backward
  321. for (int i = index+1; i < numKeys; ++i)
  322. keys[i-1] = keys[i];
  323.  
  324. // Reduce the count of keys
  325. numKeys--;
  326.  
  327. return;
  328. }
  329.  
  330. /********************************************
  331. * Function Name : removeFromNonLeaf
  332. * Pre-conditions : int index
  333. * Post-conditions: none
  334. *
  335. * A function to remove the index-th key from this node - which is a non-leaf node
  336. ********************************************/
  337. void removeFromNonLeaf(int index)
  338. {
  339.  
  340. T key = keys[index];
  341.  
  342. // If the child that precedes k (childPtrs[index]) has atleast t keys,
  343. // find the predecessor 'pred' of k in the subtree rooted at
  344. // childPtrs[index]. Replace k by pred. Recursively delete pred
  345. // in childPtrs[index]
  346. if (childPtrs[index]->numKeys >= t)
  347. {
  348. T pred = getPred(index);
  349. keys[index] = pred;
  350. childPtrs[index]->remove(pred);
  351. }
  352.  
  353. // If the child childPtrs[index] has less that t keys, examine childPtrs[index+1].
  354. // If childPtrs[index+1] has atleast t keys, find the successor 'succ' of k in
  355. // the subtree rooted at childPtrs[index+1]
  356. // Replace key by succ
  357. // Recursively delete succ in childPtrs[index+1]
  358. else if (childPtrs[index+1]->numKeys >= t)
  359. {
  360. T succ = getSucc(index);
  361. keys[index] = succ;
  362. childPtrs[index+1]->remove(succ);
  363. }
  364.  
  365. // If both childPtrs[index] and childPtrs[index+1] has less that t keys,merge k and all of childPtrs[index+1]
  366. // into childPtrs[index]
  367. // Now childPtrs[index] contains 2t-1 keys
  368. // Free childPtrs[index+1] and recursively delete k from childPtrs[index]
  369. else
  370. {
  371. merge(index);
  372. childPtrs[index]->remove(key);
  373. }
  374. return;
  375. }
  376.  
  377. /********************************************
  378. * Function Name : getPred
  379. * Pre-conditions : int index
  380. * Post-conditions: T
  381. *
  382. * A function to get predecessor of keys[index]
  383. ********************************************/
  384. T getPred(int index)
  385. {
  386. // Keep moving to the right most node until we reach a leaf
  387. BTreeNode *cur=childPtrs[index];
  388. while (!cur->leaf)
  389. cur = cur->childPtrs[cur->numKeys];
  390.  
  391. // Return the last key of the leaf
  392. return cur->keys[cur->numKeys-1];
  393. }
  394.  
  395. /********************************************
  396. * Function Name : getSucc
  397. * Pre-conditions : int index
  398. * Post-conditions: T
  399. *
  400. * Get the successor to the current key
  401. ********************************************/
  402. T getSucc(int index)
  403. {
  404.  
  405. // Keep moving the left most node starting from childPtrs[index+1] until we reach a leaf
  406. BTreeNode *cur = childPtrs[index+1];
  407. while (!cur->leaf)
  408. cur = cur->childPtrs[0];
  409.  
  410. // Return the first key of the leaf
  411. return cur->keys[0];
  412. }
  413.  
  414. /********************************************
  415. * Function Name : fill
  416. * Pre-conditions : int index
  417. * Post-conditions: none
  418. *
  419. * A function to fill child childPtrs[index] which has less than t-1 keys
  420. ********************************************/
  421. void fill(int index)
  422. {
  423.  
  424. // If the previous child(childPtrs[index-1]) has more than t-1 keys, borrow a key
  425. // from that child
  426. if (index!=0 && childPtrs[index-1]->numKeys>=t)
  427. borrowFromPrev(index);
  428.  
  429. // If the next child(childPtrs[index+1]) has more than t-1 keys, borrow a key
  430. // from that child
  431. else if (index!=numKeys && childPtrs[index+1]->numKeys >= t)
  432. borrowFromNext(index);
  433.  
  434. // Merge childPtrs[index] with its sibling
  435. // If childPtrs[index] is the last child, merge it with with its previous sibling
  436. // Otherwise merge it with its next sibling
  437. else
  438. {
  439. if (index != numKeys)
  440. merge(index);
  441. else
  442. merge(index-1);
  443. }
  444. return;
  445. }
  446.  
  447. /********************************************
  448. * Function Name : borrowFromPrev
  449. * Pre-conditions : int index
  450. * Post-conditions: none
  451. *
  452. * A function to borrow a key from childPtrs[index-1] and insert it
  453. * into childPtrs[index]
  454. ********************************************/
  455. void borrowFromPrev(int index)
  456. {
  457.  
  458. BTreeNode *child=childPtrs[index];
  459. BTreeNode *sibling=childPtrs[index-1];
  460.  
  461. // The last key from childPtrs[index-1] goes up to the parent and key[index-1]
  462. // from parent is inserted as the first key in childPtrs[index]. Thus, the loses
  463. // sibling one key and child gains one key
  464.  
  465. // Moving all key in childPtrs[index] one step ahead
  466. for (int i=child->numKeys-1; i>=0; --i)
  467. child->keys[i+1] = child->keys[i];
  468.  
  469. // If childPtrs[index] is not a leaf, move all its child pointers one step ahead
  470. if (!child->leaf)
  471. {
  472. for(int i=child->numKeys; i>=0; --i)
  473. child->childPtrs[i+1] = child->childPtrs[i];
  474. }
  475.  
  476. // Setting child's first key equal to keys[index-1] from the current node
  477. child->keys[0] = keys[index-1];
  478.  
  479. // Moving sibling's last child as childPtrs[index]'s first child
  480. if(!child->leaf)
  481. child->childPtrs[0] = sibling->childPtrs[sibling->numKeys];
  482.  
  483. // Moving the key from the sibling to the parent
  484. // This reduces the number of keys in the sibling
  485. keys[index-1] = sibling->keys[sibling->numKeys-1];
  486.  
  487. child->numKeys += 1;
  488. sibling->numKeys -= 1;
  489.  
  490. return;
  491. }
  492.  
  493. /********************************************
  494. * Function Name : borrowFromNext
  495. * Pre-conditions : int index
  496. * Post-conditions: none
  497. *
  498. * A function to borrow a key from the childPtrs[index+1] and place
  499. * it in childPtrs[index]
  500. ********************************************/
  501. void borrowFromNext(int index)
  502. {
  503.  
  504. BTreeNode *child=childPtrs[index];
  505. BTreeNode *sibling=childPtrs[index+1];
  506.  
  507. // keys[index] is inserted as the last key in childPtrs[index]
  508. child->keys[(child->numKeys)] = keys[index];
  509.  
  510. // Sibling's first child is inserted as the last child
  511. // into childPtrs[index]
  512. if (!(child->leaf))
  513. child->childPtrs[(child->numKeys)+1] = sibling->childPtrs[0];
  514.  
  515. //The first key from sibling is inserted into keys[index]
  516. keys[index] = sibling->keys[0];
  517.  
  518. // Moving all keys in sibling one step behind
  519. for (int i=1; i<sibling->numKeys; ++i)
  520. sibling->keys[i-1] = sibling->keys[i];
  521.  
  522. // Moving the child pointers one step behind
  523. if (!sibling->leaf)
  524. {
  525. for(int i=1; i<=sibling->numKeys; ++i)
  526. sibling->childPtrs[i-1] = sibling->childPtrs[i];
  527. }
  528.  
  529. // Increasing and decreasing the key count of childPtrs[index] and childPtrs[index+1]
  530. // respectively
  531. child->numKeys += 1;
  532. sibling->numKeys -= 1;
  533.  
  534. return;
  535. }
  536.  
  537. /********************************************
  538. * Function Name : merge
  539. * Pre-conditions : int index
  540. * Post-conditions: none
  541. *
  542. * A function to merge childPtrs[index] with childPtrs[index+1]
  543. * childPtrs[index+1] is freed after merging
  544. ********************************************/
  545. void merge(int index)
  546. {
  547. BTreeNode<T> *child = childPtrs[index];
  548. BTreeNode<T> *sibling = childPtrs[index+1];
  549.  
  550. // Pulling a key from the current node and inserting it into (t-1)th
  551. // position of childPtrs[index]
  552. child->keys[t-1] = keys[index];
  553.  
  554. // Copying the keys from childPtrs[index+1] to childPtrs[index] at the end
  555. for (int i=0; i<sibling->numKeys; ++i)
  556. child->keys[i+t] = sibling->keys[i];
  557.  
  558. // Copying the child pointers from childPtrs[index+1] to childPtrs[index]
  559. if (!child->leaf)
  560. {
  561. for(int i=0; i<=sibling->numKeys; ++i)
  562. child->childPtrs[i+t] = sibling->childPtrs[i];
  563. }
  564.  
  565. // Moving all keys after index in the current node one step before -
  566. // to fill the gap created by moving keys[index] to childPtrs[index]
  567. for (int i=index+1; i<numKeys; ++i)
  568. keys[i-1] = keys[i];
  569.  
  570. // Moving the child pointers after (index+1) in the current node one
  571. // step before
  572. for (int i=index+2; i<=numKeys; ++i)
  573. childPtrs[i-1] = childPtrs[i];
  574.  
  575. // Updating the key count of child and the current node
  576. child->numKeys += sibling->numKeys+1;
  577. numKeys--;
  578.  
  579. // Freeing the memory occupied by sibling
  580. delete(sibling);
  581. return;
  582. }
  583.  
  584. };
  585.  
  586. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement