Opptur

B-Tree (3rd deletion case incomplete)

Jul 6th, 2017
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.58 KB | None | 0 0
  1. // B-Tree.h
  2. #pragma once
  3. #include <list>
  4. #include <vector>
  5.  
  6. using namespace std;
  7.  
  8. template <class T>
  9. class Node
  10. {
  11. public:
  12.     unsigned nr_keys = 0;
  13.     T *keys = nullptr;
  14.     Node<T> **children = nullptr;
  15.     bool leaf = false;
  16.  
  17.     Node(unsigned nr_keys)
  18.     {
  19.         keys = new T[nr_keys]();
  20.         children = new Node<T>*[nr_keys + 1]();
  21.     }
  22.  
  23.     ~Node()
  24.     {
  25.         if (keys)
  26.             delete[] keys;
  27.         if (children)
  28.             delete[] children;
  29.     }
  30. };
  31.  
  32. template <class T>
  33. class BTree
  34. {
  35. private:
  36.     Node<T> *root = nullptr;
  37.     unsigned t = 0, keys_min = 0, keys_max = 0;
  38.  
  39.     void split_child(Node<T> *parent, unsigned child_index)
  40.     {
  41.         Node<T> *child = parent->children[child_index];
  42.  
  43.         // creating the new child node
  44.         Node<T> *new_child = new Node<T>(keys_max);
  45.         new_child->leaf = child->leaf;
  46.  
  47.         // moving the right child keys to the new child
  48.         child->nr_keys = keys_min;
  49.         new_child->nr_keys = keys_min;
  50.         for (unsigned i = 0; i < keys_min; i++)
  51.             new_child->keys[i] = child->keys[i + t];
  52.  
  53.         // moving the right children to the new child
  54.         if (!child->leaf)
  55.             for (unsigned i = 0; i < keys_min + 1; i++)
  56.                 new_child->children[i] = child->children[i + keys_min + 1];
  57.  
  58.         // moving the parent right keys to make room for the new key
  59.         for (unsigned i = parent->nr_keys; i > child_index; i--)
  60.             parent->keys[i] = parent->keys[i - 1];
  61.  
  62.         // inserting the new key
  63.         parent->keys[child_index] = child->keys[keys_min];
  64.         parent->nr_keys++;
  65.  
  66.         // moving the parent right children to make room for the new child
  67.         for (unsigned i = parent->nr_keys + 1; i > child_index; i--)
  68.             parent->children[i] = parent->children[i - 1];
  69.  
  70.         // inserting the new child
  71.         parent->children[child_index + 1] = new_child;
  72.     }
  73.  
  74.     void insert_rootnotfull(Node<T> *node, T key)
  75.     {
  76.         // i = the last key
  77.         unsigned i = node->nr_keys - 1;
  78.  
  79.         // if we are on a leaf we just insert the element
  80.         if (node->leaf)
  81.         {
  82.             // we move the elements while our key is smaller than the current key
  83.             while (i >= 0 && key < node->keys[i])
  84.             {
  85.                 node->keys[i + 1] = node->keys[i];
  86.                 i--;
  87.             }
  88.  
  89.             // in the empty space we put the new key
  90.             node->keys[i + 1] = key;
  91.  
  92.             // we increment the number of keys found in the node
  93.             node->nr_keys++;
  94.         }
  95.  
  96.         // otherwise we have to get to a leaf
  97.         else
  98.         {
  99.             // we find the child in which we should place our key
  100.             while (i >= 0 && key < node->keys[i])
  101.                 i--;
  102.  
  103.             // fix the overshoot
  104.             i++;
  105.  
  106.             // if the child is full, we split it
  107.             if (node->children[i]->nr_keys == keys_max)
  108.             {
  109.                 split_child(node, i);
  110.  
  111.                 // if the key that has been pushed up is smaller than our key, we go one key further
  112.                 if (key > node->keys[i])
  113.                     i++;
  114.             }
  115.  
  116.             // try to insert the key in the found and split child
  117.             insert_rootnotfull(node->children[i], key);
  118.         }
  119.     }
  120.  
  121. public:
  122.     BTree(unsigned t)
  123.     {
  124.         this->t = t;
  125.         keys_min = t - 1;
  126.         keys_max = 2 * t - 1;
  127.  
  128.         root = new Node<T>(keys_max);
  129.         root->leaf = true;
  130.     }
  131.  
  132.     void print()
  133.     {
  134.         vector<Node<T>*> vect;
  135.         vect.emplace_back(root);
  136.  
  137.         while (!vect.empty())
  138.         {
  139.             unsigned i, j, size = vect.size();
  140.             for (i = 0; i < size; i++)
  141.             {
  142.                 for (j = 0; j < vect[i]->nr_keys; j++)
  143.                 {
  144.                     cout << vect[i]->keys[j] << ' ';
  145.                     if(!vect[i]->leaf)
  146.                         vect.emplace_back(vect[i]->children[j]);
  147.                 }
  148.                 if (!vect[i]->leaf)
  149.                     vect.emplace_back(vect[i]->children[j]);
  150.                 cout << "          ";
  151.             }
  152.             vect.erase(vect.begin(), vect.begin()+size);
  153.             cout << endl;
  154.         }
  155.     }
  156.  
  157.     // returns true if removal has been successful and false if not
  158.     bool remove(Node<T> *current_node, T key)
  159.     {
  160.         // i = key index
  161.         //unsigned i = findindex(current_node, key);
  162.         unsigned i = 0;
  163.         while (i < current_node.nr_keys && key > current_node.keys[i])
  164.             i++;
  165.         // cases 1 and 2
  166.         if (i < current_node->nr_keys && key == current_node->keys[i])
  167.             // case 1 (if the key is in the current_node and current_node is a leaf, delete key from current_node)
  168.             if (current_node->leaf)
  169.             {
  170.                 // move the right side elements of keys[i] to the left by one position (over the current element)
  171.                 for (int j = i; j < current_node->nr_keys - 1; j++)
  172.                     current_node->keys[j] = current_node->keys[j + 1];
  173.                 // decrease the number of keys by one
  174.                 current_node->nr_keys--;
  175.                 return true;
  176.             }
  177.             // case 2 (if the key is in the current_node and current_node is internal)
  178.             else
  179.             {
  180.                 // case 2a (if the child that precedes key in current_node has at least keys_min+1 keys)
  181.                 if (current_node->children[i]->nr_keys >= keys_min + 1)
  182.                 {
  183.                     // find the predecessor of key starting from key's left child
  184.                     Node<T> *predecessor_node = current_node->children[i];
  185.                     // the predecessor will be the lowest and most right key starting from key's left child
  186.                     while (!predecessor_node->leaf)
  187.                         predecessor_node = predecessor_node->children[predecessor_node->nr_keys];
  188.                     T predecessor = predecessor_node->keys[predecessor_node->nr_keys - 1];
  189.                     // delete the predecessor
  190.                     remove(predecessor_node, predecessor);
  191.                     // replace key from current_node with predecessor
  192.                     current_node->keys[i] = predecessor;
  193.                     return true;
  194.                 }
  195.                 // case 2b (if the child that precedes key in current_node doesn't have at least keys_min+1 keys but the child that succedes key has at least keys_min+1 keys)
  196.                 else if (current_node->children[i+1]->nr_keys >= keys_min + 1)
  197.                 {
  198.                     // find the successor of key starting from key's right child
  199.                     Node<T> *successor_node = current_node->children[i+1];
  200.                     // the successor will be the lowest and most left key starting from key's right child
  201.                     while (!successor_node->leaf)
  202.                         successor_node = successor_node->children[0];
  203.                     T successor = successor_node->keys[0];
  204.                     // delete the successor
  205.                     remove(successor_node, successor);
  206.                     // replace key from current_node with successor
  207.                     current_node->keys[i] = successor;
  208.                     return true;
  209.                 }
  210.                 // case 2c (both the child that precedes key and the child that succedes key have only keys_min keys)
  211.                 else
  212.                 {
  213.                     // merge key and the child that succedes key into the child that precedes key (which now contains max_keys keys)
  214.                     Node<T> *predecessor_node = current_node->children[i];
  215.                     Node<T> *successor_node = current_node->children[i + 1];
  216.                     predecessor_node->keys[predecessor_node->nr_keys] = key;
  217.                     // this causes the last child (children[nr_keys]) to be empty
  218.                     predecessor_node->nr_keys++;
  219.                     for (int i = 0; i < successor_node->nr_keys; i++)
  220.                     {
  221.                         predecessor_node->keys[predecessor_node->nr_keys + i] = successor_node->keys[i];
  222.                         // because the last child is empty initially (see above comment), we begin with it
  223.                         predecessor_node->children[predecessor_node->nr_keys + i] = successor_node->children[i];
  224.                     }
  225.                     predecessor_node->nr_keys += successor_node->nr_keys;
  226.                     // we insert the supplementar child
  227.                     predecessor_node->children[predecessor_node->nr_keys] = successor_node->children[successor_node->nr_keys];
  228.  
  229.                     // remove key's right child
  230.                     delete successor_node;
  231.  
  232.                     // remove the key and its right child from current_node
  233.                     for (int j = i; j < current_node->nr_keys-1; j++)
  234.                     {
  235.                         current_node->keys[j] = current_node->keys[j+1];
  236.                         current_node->children[j+1] = current_node->children[j+2];
  237.                     }
  238.                     current_node->nr_keys--;
  239.  
  240.                     // recursively remove key from predecessor_node
  241.                     remove(predecessor_node, key);
  242.                 }
  243.             }
  244.         // case 3 (key is not present in current_node)
  245.         else
  246.             // the key is not present in the tree
  247.             if (current_node->leaf)
  248.                 return false;
  249.             // case 3a and 3b
  250.             else if (current_node->children[i]->nr_keys == keys_min)
  251.             {
  252.                 // case 3a - borrow from previous
  253.                 if (i > 0 && current_node->children[i - 1]->nr_keys == keys_min + 1)
  254.                 {
  255.                     Node<T> *child = current_node->children[i];
  256.                     Node<T> *sibling = current_node->children[i - 1];
  257.  
  258.                     // current key comes down into the child
  259.                     child->keys[child->nr_keys] = current_node->keys[i];
  260.                     child->nr_keys++;
  261.  
  262.                 }
  263.                 // case 3a - borrow from next
  264.                 else if (i < current_node->nr_keys && current_node->children[i + 1]->nr_keys == keys_min + 1)
  265.                 {
  266.  
  267.                 }
  268.                 // case 3b - merge
  269.                 else
  270.                 {
  271.                     // verify if root is empty and replace it with first child if so
  272.                     if (root->nr_keys == 0)
  273.                     {
  274.                         Node<T> *temp = root->children[0];
  275.                         delete root;
  276.                         root = temp;
  277.                     }
  278.                 }
  279.             }
  280.             else
  281.             {
  282.                 remove(current_node->children[i], key);
  283.             }
  284.     }
  285.     void insert(T key)
  286.     {
  287.         // if the root is full, we need to make another one that can accept our element
  288.         if (root->nr_keys == keys_max)
  289.         {
  290.             // create a new root
  291.             Node<T> *new_root = new Node<T>(keys_max);
  292.  
  293.             // the first child of the new root is the old root
  294.             new_root->children[0] = root;
  295.  
  296.             // the root is now the new root
  297.             root = new_root;
  298.  
  299.             // we now split the first child of the new root (the old root)
  300.             split_child(root, 0);
  301.         }
  302.  
  303.         // we can now insert the new element
  304.         insert_rootnotfull(root, key);
  305.     }
  306.     pair<Node<T>, unsigned> search(Node<T> *current_node, T key)
  307.     {
  308.         unsigned i = 0;
  309.         while (i < current_node.nr_keys && key < current_node.keys[i])
  310.             i++;
  311.         if (i < current_node.nr_keys && k == current_node.keys[i])
  312.             return pair<Node<T>, unsigned>(current_node, i);
  313.         else
  314.             if (current_node.leaf)
  315.                 return nullptr;
  316.             else
  317.                 search(current_node.children[i], key);
  318.     }
  319. };
  320.  
  321. // Source.cpp
  322. #include <iostream>
  323. #include "B-Tree.h"
  324.  
  325. using namespace std;
  326.  
  327. void main()
  328. {
  329.     BTree<char> bt(3);
  330.     char temp;
  331.     cin >> temp;
  332.     while (temp != '0')
  333.     {
  334.         bt.insert(temp);
  335.         cin >> temp;
  336.     }
  337.     bt.print();
  338. }
Advertisement
Add Comment
Please, Sign In to add comment