Insertion in a B+ tree - GeeksforGeeks

24 Nov, 2021
Prerequisite: Introduction of B+ treesIn this article, we will discuss that how to insert a node in B+ Tree. During insertion following properties of B+ Tree must be followed:  
Each node except root can have a maximum of M children and at least ceil(M/2) children.
Each node can contain a maximum of M – 1 keys and a minimum of ceil(M/2) – 1 keys.
The root has at least two children and atleast one search key.
While insertion overflow of the node occurs when it contains more than M – 1 search key values.
Here M is the order of B+ tree. 
 
Every element is inserted into a leaf node. So, go to the appropriate leaf node.Insert the key into the leaf node in increasing order only if there is no overflow. If there is an overflow go ahead with the following steps mentioned below to deal with overflow while maintaining the B+ Tree properties.
Every element is inserted into a leaf node. So, go to the appropriate leaf node.
Insert the key into the leaf node in increasing order only if there is no overflow. If there is an overflow go ahead with the following steps mentioned below to deal with overflow while maintaining the B+ Tree properties.
 
Case 1: Overflow in leaf node  
Split the leaf node into two nodes.First node contains ceil((m-1)/2) values.Second node contains the remaining values.Copy the smallest search key value from second node to the parent node.(Right biased)
Split the leaf node into two nodes.
First node contains ceil((m-1)/2) values.
Second node contains the remaining values.
Copy the smallest search key value from second node to the parent node.(Right biased)
Below is the illustration of inserting 8 into B+ Tree of order of 5:  
Case 2: Overflow in non-leaf node  
Split the non leaf node into two nodes.First node contains ceil(m/2)-1 values.Move the smallest among remaining to the parent.Second node contains the remaining keys.
Split the non leaf node into two nodes.
First node contains ceil(m/2)-1 values.
Move the smallest among remaining to the parent.
Second node contains the remaining keys.
Below is the illustration of inserting 15 into B+ Tree of order of 5:  
 
Problem: Insert the following key values 6, 16, 26, 36, 46 on a B+ tree with order = 3. Solution: Step 1: The order is 3 so at maximum in a node so there can be only 2 search key values. As insertion happens on a leaf node only in a B+ tree so insert search key value 6 and 16 in increasing order in the node. Below is the illustration of the same:  
Step 2: We cannot insert 26 in the same node as it causes an overflow in the leaf node, We have to split the leaf node according to the rules. First part contains ceil((3-1)/2) values i.e., only 6. The second node contains the remaining values i.e., 16 and 26. Then also copy the smallest search key value from the second node to the parent node i.e., 16 to the parent node. Below is the illustration of the same:  
Step 3: Now the next value is 36 that is to be inserted after 26 but in that node, it causes an overflow again in that leaf node. Again follow the above steps to split the node. First part contains ceil((3-1)/2) values i.e., only 16. The second node contains the remaining values i.e., 26 and 36. Then also copy the smallest search key value from the second node to the parent node i.e., 26 to the parent node. Below is the illustration of the same: The illustration is shown in the diagram below.  
Step 4: Now we have to insert 46 which is to be inserted after 36 but it causes an overflow in the leaf node. So we split the node according to the rules. The first part contains 26 and the second part contains 36 and 46 but now we also have to copy 36 to the parent node but it causes overflow as only two search key values can be accommodated in a node. Now follow the steps to deal with overflow in the non-leaf node. First node contains ceil(3/2)-1 values i.e. ’16’. Move the smallest among remaining to the parent i.e ’26’ will be the new parent node. The second node contains the remaining keys i.e ’36’ and the rest of the leaf nodes remain the same. Below is the illustration of the same:  
Below is the implementation of insertion in the B+ tree: 
C++
Python3
// C++ program for implementing B+ Tree#include <climits>#include <fstream>#include <iostream>#include <sstream>using namespace std;int MAX = 3; // BP nodeclass Node {    bool IS_LEAF;    int *key, size;    Node** ptr;    friend class BPTree; public:    Node();}; // BP treeclass BPTree {    Node* root;    void insertInternal(int,                        Node*,                        Node*);    Node* findParent(Node*, Node*); public:    BPTree();    void search(int);    void insert(int);    void display(Node*);    Node* getRoot();}; // Constructor of NodeNode::Node(){    key = new int[MAX];    ptr = new Node*[MAX + 1];} // Initialise the BPTree NodeBPTree::BPTree(){    root = NULL;} // Function to find any element// in B+ Treevoid BPTree::search(int x){     // If tree is empty    if (root == NULL) {        cout << "Tree is empty\n";    }     // Traverse to find the value    else {         Node* cursor = root;         // Till we reach leaf node        while (cursor->IS_LEAF == false) {             for (int i = 0;                 i < cursor->size; i++) {                 // If the element to be                // found is not present                if (x < cursor->key[i]) {                    cursor = cursor->ptr[i];                    break;                }                 // If reaches end of the                // cursor node                if (i == cursor->size - 1) {                    cursor = cursor->ptr[i + 1];                    break;                }            }        }         // Traverse the cursor and find        // the node with value x        for (int i = 0;             i < cursor->size; i++) {             // If found then return            if (cursor->key[i] == x) {                cout << "Found\n";                return;            }        }         // Else element is not present        cout << "Not found\n";    }} // Function to implement the Insert// Operation in B+ Treevoid BPTree::insert(int x){     // If root is null then return    // newly created node    if (root == NULL) {        root = new Node;        root->key[0] = x;        root->IS_LEAF = true;        root->size = 1;    }     // Traverse the B+ Tree    else {        Node* cursor = root;        Node* parent;         // Till cursor reaches the        // leaf node        while (cursor->IS_LEAF               == false) {             parent = cursor;             for (int i = 0;                 i < cursor->size;                 i++) {                 // If found the position                // where we have to insert                // node                if (x < cursor->key[i]) {                    cursor                        = cursor->ptr[i];                    break;                }                 // If reaches the end                if (i == cursor->size - 1) {                    cursor                        = cursor->ptr[i + 1];                    break;                }            }        }         if (cursor->size < MAX) {            int i = 0;            while (x > cursor->key[i]                   && i < cursor->size) {                i++;            }             for (int j = cursor->size;                 j > i; j--) {                cursor->key[j]                    = cursor->key[j - 1];            }             cursor->key[i] = x;            cursor->size++;             cursor->ptr[cursor->size]                = cursor->ptr[cursor->size - 1];            cursor->ptr[cursor->size - 1] = NULL;        }         else {             // Create a newLeaf node            Node* newLeaf = new Node;             int virtualNode[MAX + 1];             // Update cursor to virtual            // node created            for (int i = 0; i < MAX; i++) {                virtualNode[i]                    = cursor->key[i];            }            int i = 0, j;             // Traverse to find where the new            // node is to be inserted            while (x > virtualNode[i]                   && i < MAX) {                i++;            }             // Update the current virtual            // Node to its previous            for (int j = MAX + 1;                 j > i; j--) {                virtualNode[j]                    = virtualNode[j - 1];            }             virtualNode[i] = x;            newLeaf->IS_LEAF = true;             cursor->size = (MAX + 1) / 2;            newLeaf->size                = MAX + 1 - (MAX + 1) / 2;             cursor->ptr[cursor->size]                = newLeaf;             newLeaf->ptr[newLeaf->size]                = cursor->ptr[MAX];             cursor->ptr[MAX] = NULL;             // Update the current virtual            // Node's key to its previous            for (i = 0;                 i < cursor->size; i++) {                cursor->key[i]                    = virtualNode[i];            }             // Update the newLeaf key to            // virtual Node            for (i = 0, j = cursor->size;                 i < newLeaf->size;                 i++, j++) {                newLeaf->key[i]                    = virtualNode[j];            }             // If cursor is the root node            if (cursor == root) {                 // Create a new Node                Node* newRoot = new Node;                 // Update rest field of                // B+ Tree Node                newRoot->key[0] = newLeaf->key[0];                newRoot->ptr[0] = cursor;                newRoot->ptr[1] = newLeaf;                newRoot->IS_LEAF = false;                newRoot->size = 1;                root = newRoot;            }            else {                 // Recursive Call for                // insert in internal                insertInternal(newLeaf->key[0],                               parent,                               newLeaf);            }        }    }} // Function to implement the Insert// Internal Operation in B+ Treevoid BPTree::insertInternal(int x,                            Node* cursor,                            Node* child){     // If we doesn't have overflow    if (cursor->size < MAX) {        int i = 0;         // Traverse the child node        // for current cursor node        while (x > cursor->key[i]               && i < cursor->size) {            i++;        }         // Traverse the cursor node        // and update the current key        // to its previous node key        for (int j = cursor->size;             j > i; j--) {             cursor->key[j]                = cursor->key[j - 1];        }         // Traverse the cursor node        // and update the current ptr        // to its previous node ptr        for (int j = cursor->size + 1;             j > i + 1; j--) {            cursor->ptr[j]                = cursor->ptr[j - 1];        }         cursor->key[i] = x;        cursor->size++;        cursor->ptr[i + 1] = child;    }     // For overflow, break the node    else {         // For new Interval        Node* newInternal = new Node;        int virtualKey[MAX + 1];        Node* virtualPtr[MAX + 2];         // Insert the current list key        // of cursor node to virtualKey        for (int i = 0; i < MAX; i++) {            virtualKey[i] = cursor->key[i];        }         // Insert the current list ptr        // of cursor node to virtualPtr        for (int i = 0; i < MAX + 1; i++) {            virtualPtr[i] = cursor->ptr[i];        }         int i = 0, j;         // Traverse to find where the new        // node is to be inserted        while (x > virtualKey[i]               && i < MAX) {            i++;        }         // Traverse the virtualKey node        // and update the current key        // to its previous node key        for (int j = MAX + 1;             j > i; j--) {             virtualKey[j]                = virtualKey[j - 1];        }         virtualKey[i] = x;         // Traverse the virtualKey node        // and update the current ptr        // to its previous node ptr        for (int j = MAX + 2;             j > i + 1; j--) {            virtualPtr[j]                = virtualPtr[j - 1];        }         virtualPtr[i + 1] = child;        newInternal->IS_LEAF = false;         cursor->size            = (MAX + 1) / 2;         newInternal->size            = MAX - (MAX + 1) / 2;         // Insert new node as an        // internal node        for (i = 0, j = cursor->size + 1;             i < newInternal->size;             i++, j++) {             newInternal->key[i]                = virtualKey[j];        }         for (i = 0, j = cursor->size + 1;             i < newInternal->size + 1;             i++, j++) {             newInternal->ptr[i]                = virtualPtr[j];        }         // If cursor is the root node        if (cursor == root) {             // Create a new root node            Node* newRoot = new Node;             // Update key value            newRoot->key[0]                = cursor->key[cursor->size];             // Update rest field of            // B+ Tree Node            newRoot->ptr[0] = cursor;            newRoot->ptr[1] = newInternal;            newRoot->IS_LEAF = false;            newRoot->size = 1;            root = newRoot;        }         else {             // Recursive Call to insert            // the data            insertInternal(cursor->key[cursor->size],                           findParent(root,                                      cursor),                           newInternal);        }    }} // Function to find the parent nodeNode* BPTree::findParent(Node* cursor,                         Node* child){    Node* parent;     // If cursor reaches the end of Tree    if (cursor->IS_LEAF        || (cursor->ptr[0])->IS_LEAF) {        return NULL;    }     // Traverse the current node with    // all its child    for (int i = 0;         i < cursor->size + 1; i++) {         // Update the parent for the        // child Node        if (cursor->ptr[i] == child) {            parent = cursor;            return parent;        }         // Else recursively traverse to        // find child node        else {            parent                = findParent(cursor->ptr[i],                             child);             // If parent is found, then            // return that parent node            if (parent != NULL)                return parent;        }    }     // Return parent node    return parent;} // Function to get the root NodeNode* BPTree::getRoot(){    return root;} // Driver Codeint main(){    BPTree node;     // Create B+ Tree    node.insert(6);    node.insert(16);    node.insert(26);    node.insert(36);    node.insert(46);     // Function Call to search node    // with value 16    node.search(16);     return 0;}
# Python3 program for implementing B+ Tree MAX = 3 # BP nodeclass Node :    def __init__(self):        self.IS_LEAF=False        self.key, self.size=[None]*MAX,0        self.ptr=[None]*(MAX+1)  # BP treeclass BPTree : # Initialise the BPTree Node    def __init__(self):        self.root = None  # Function to find any element# in B+ Tree    def search(self,x):         # If tree is empty        if (self.root == None) :            cout << "Tree is empty\n"                  # Traverse to find the value        else :             cursor = self.root             # Till we reach leaf node            while (not cursor.IS_LEAF) :                 for i in range(cursor.size) :                     # If the element to be                    # found is not present                    if (x < cursor.key[i]) :                        cursor = cursor.ptr[i]                        break                                          # If reaches end of the                    # cursor node                    if (i == cursor.size - 1) :                        cursor = cursor.ptr[i + 1]                        break                                                                # Traverse the cursor and find            # the node with value x            for i in range(cursor.size):                 # If found then return                if (cursor.key[i] == x) :                    print("Found")                    return                                           # Else element is not present            print("Not found")           # Function to implement the Insert    # Operation in B+ Tree    def insert(self, x):         # If root is None then return        # newly created node        if (self.root == None) :            self.root = Node()            self.root.key[0] = x            self.root.IS_LEAF = True            self.root.size = 1                  # Traverse the B+ Tree        else :            cursor = self.root            parent=None            # Till cursor reaches the            # leaf node            while (not cursor.IS_LEAF) :                 parent = cursor                 for i in range(cursor.size) :                     # If found the position                    # where we have to insert                    # node                    if (x < cursor.key[i]) :                        cursor = cursor.ptr[i]                        break                                          # If reaches the end                    if (i == cursor.size - 1) :                        cursor = cursor.ptr[i + 1]                        break                                                  if (cursor.size < MAX) :                i = 0                while (i < cursor.size and x > cursor.key[i]):                    i+=1                                  for j in range(cursor.size,i,-1):                    cursor.key[j] = cursor.key[j - 1]                                  cursor.key[i] = x                cursor.size+=1                 cursor.ptr[cursor.size] = cursor.ptr[cursor.size - 1]                cursor.ptr[cursor.size - 1] = None                          else :                 # Create a newLeaf node                newLeaf = Node()                 virtualNode=[None]*(MAX + 1)                 # Update cursor to virtual                # node created                for i in range(MAX):                    virtualNode[i] = cursor.key[i]                                 i = 0                 # Traverse to find where the new                # node is to be inserted                while (i < MAX and x > virtualNode[i]) :                    i+=1                                  # Update the current virtual                # Node to its previous                for j in range(MAX,i,-1) :                    virtualNode[j] = virtualNode[j - 1]                                  virtualNode[i] = x                newLeaf.IS_LEAF = True                 cursor.size = int((MAX + 1) / 2)                newLeaf.size = int(MAX + 1 - (MAX + 1) / 2)                 cursor.ptr[cursor.size] = newLeaf                 newLeaf.ptr[newLeaf.size] = cursor.ptr[MAX]                 cursor.ptr[MAX] = None                 # Update the current virtual                # Node's key to its previous                for i in range(cursor.size):                    cursor.key[i] = virtualNode[i]                                  # Update the newLeaf key to                # virtual Node                j=cursor.size                for i in range(newLeaf.size):                    newLeaf.key[i] = virtualNode[j]                    j+=1                                  # If cursor is the root node                if (cursor == self.root) :                     # Create a new Node                    newRoot = Node()                     # Update rest field of                    # B+ Tree Node                    newRoot.key[0] = newLeaf.key[0]                    newRoot.ptr[0] = cursor                    newRoot.ptr[1] = newLeaf                    newRoot.IS_LEAF = False                    newRoot.size = 1                    root = newRoot                                 else :                     # Recursive Call for                    # insert in internal                    insertInternal(newLeaf.key[0],                                parent,                                newLeaf)                             # Function to implement the Insert# Internal Operation in B+ Treedef insertInternal(x, cursor, child):     # If we doesn't have overflow    if (cursor.size < MAX) :        i = 0         # Traverse the child node        # for current cursor node        while (x > cursor.key[i] and i < cursor.size) :            i+=1                  # Traverse the cursor node        # and update the current key        # to its previous node key        for j in range(cursor.size,i,-1) :             cursor.key[j] = cursor.key[j - 1]                 # Traverse the cursor node        # and update the current ptr        # to its previous node ptr        for j in range(cursor.size + 1, i + 1,-1):            cursor.ptr[j] = cursor.ptr[j - 1]                  cursor.key[i] = x        cursor.size+=1        cursor.ptr[i + 1] = child          # For overflow, break the node    else :         # For new Interval        newInternal = Node()        virtualKey=[None]*(MAX + 1)        virtualPtr=[None]*(MAX + 2)         # Insert the current list key        # of cursor node to virtualKey        for i in range(MAX) :            virtualKey[i] = cursor.key[i]                  # Insert the current list ptr        # of cursor node to virtualPtr        for i in range(MAX + 1):            virtualPtr[i] = cursor.ptr[i]                  i = 0         # Traverse to find where the new        # node is to be inserted        while (x > virtualKey[i] and i < MAX) :            i+=1                  # Traverse the virtualKey node        # and update the current key        # to its previous node key        for j in range(MAX + 1,i,-1):             virtualKey[j] = virtualKey[j - 1]                  virtualKey[i] = x         # Traverse the virtualKey node        # and update the current ptr        # to its previous node ptr        for j in range(MAX + 2, i + 1,-1) :            virtualPtr[j] = virtualPtr[j - 1]                  virtualPtr[i + 1] = child        newInternal.IS_LEAF = false         cursor.size = (MAX + 1) / 2         newInternal.size = MAX - (MAX + 1) / 2         # Insert new node as an        # internal node        j = cursor.size + 1        for i in range(newInternal.size):            newInternal.key[i] = virtualKey[j]            j+=1                  j = cursor.size + 1        for i in range(newInternal.size):            newInternal.ptr[i] = virtualKey[j]            j+=1                  # If cursor is the root node        if (cursor == self.root) :             # Create a new root node            newRoot = self.root             # Update key value            newRoot.key[0] = cursor.key[cursor.size]             # Update rest field of            # B+ Tree Node            newRoot.ptr[0] = cursor            newRoot.ptr[1] = newInternal            newRoot.IS_LEAF = false            newRoot.size = 1            root = newRoot                  else :             # Recursive Call to insert            # the data            insertInternal(cursor.key[cursor.size],                           findParent(root,                                      cursor),                           newInternal)                    # Function to find the parent node    def findParent(self, cursor, child):        # If cursor reaches the end of Tree        if (cursor.IS_LEAF or (cursor.ptr[0]).IS_LEAF) :            return None                  # Traverse the current node with        # all its child        for i in range(cursor.size + 1) :             # Update the parent for the            # child Node            if (cursor.ptr[i] == child) :                parent = cursor                return parent                          # Else recursively traverse to            # find child node            else :                parent = findParent(cursor.ptr[i], child)                 # If parent is found, then                # return that parent node                if (parent != None):                    return parent                               # Return parent node        return parent      # Function to get the root Node    def getRoot(self):        return self.root  # Driver Codeif __name__=='__main__':    node=BPTree()     # Create B+ Tree    node.insert(6)    node.insert(16)    node.insert(26)    node.insert(36)    node.insert(46)     # Function Call to search node    # with value 16    node.search(16)
Found
 
amartyaghoshgfg
B and B+ Trees
Data Structures-B and B+ Trees
Algorithms
Data Structures
Tree
Data Structures
Tree
Algorithms
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
DSA Sheet by Love Babbar
SCAN (Elevator) Disk Scheduling Algorithms
Program for SSTF disk scheduling algorithm
Quadratic Probing in Hashing
Rail Fence Cipher - Encryption and Decryption
DSA Sheet by Love Babbar
Doubly Linked List | Set 1 (Introduction and Insertion)
Implementing a Linked List in Java using Class
Insertion and Deletion in Heaps
Abstract Data Types