Insertion in B+ Tree

Insertion in a B+ tree involves placing a new key-value pair into the appropriate leaf node and ensuring tree balance through splits and updates.

Step-by-step algorithm:

  1. Insertion:
    • Search for the leaf node to insert the key-value pair.
    • If the leaf node is full, split it.
    • Propagate median key to parent if necessary.
    • Split parent if full.
    • Repeat until balanced.
  2. Search:
    • Traverse down the tree to find leaf node.
    • Search for key in leaf node.
    • Return value if found, else indicate failure.
  3. Print Tree:
    • Traverse tree to print its structure.
  4. Example Operations:
    • Insert key-value pairs.
    • Search for specific keys.
    • Print the tree structure.

Below is the implementation of the above idea:

Python3
import math

# Node creation
class Node:
    def __init__(self, order):
        self.order = order
        self.values = []
        self.keys = []
        self.nextKey = None
        self.parent = None
        self.check_leaf = False

    # Insert at the leaf
    def insert_at_leaf(self, leaf, value, key):
        if (self.values):
            temp1 = self.values
            for i in range(len(temp1)):
                if (value == temp1[i]):
                    self.keys[i].append(key)
                    break
                elif (value < temp1[i]):
                    self.values = self.values[:i] + [value] + self.values[i:]
                    self.keys = self.keys[:i] + [[key]] + self.keys[i:]
                    break
                elif (i + 1 == len(temp1)):
                    self.values.append(value)
                    self.keys.append([key])
                    break
        else:
            self.values = [value]
            self.keys = [[key]]


# B plus tree
class BplusTree:
    def __init__(self, order):
        self.root = Node(order)
        self.root.check_leaf = True

    # Insert operation
    def insert(self, value, key):
        value = str(value)
        old_node = self.search(value)
        old_node.insert_at_leaf(old_node, value, key)

        if (len(old_node.values) == old_node.order):
            node1 = Node(old_node.order)
            node1.check_leaf = True
            node1.parent = old_node.parent
            mid = int(math.ceil(old_node.order / 2)) - 1
            node1.values = old_node.values[mid + 1:]
            node1.keys = old_node.keys[mid + 1:]
            node1.nextKey = old_node.nextKey
            old_node.values = old_node.values[:mid + 1]
            old_node.keys = old_node.keys[:mid + 1]
            old_node.nextKey = node1
            self.insert_in_parent(old_node, node1.values[0], node1)

    # Search operation for different operations
    def search(self, value):
        current_node = self.root
        while(current_node.check_leaf == False):
            temp2 = current_node.values
            for i in range(len(temp2)):
                if (value == temp2[i]):
                    current_node = current_node.keys[i + 1]
                    break
                elif (value < temp2[i]):
                    current_node = current_node.keys[i]
                    break
                elif (i + 1 == len(current_node.values)):
                    current_node = current_node.keys[i + 1]
                    break
        return current_node

    # Find the node
    def find(self, value, key):
        l = self.search(value)
        for i, item in enumerate(l.values):
            if item == value:
                if key in l.keys[i]:
                    return True
                else:
                    return False
        return False

    # Inserting at the parent
    def insert_in_parent(self, n, value, ndash):
        if (self.root == n):
            rootNode = Node(n.order)
            rootNode.values = [value]
            rootNode.keys = [n, ndash]
            self.root = rootNode
            n.parent = rootNode
            ndash.parent = rootNode
            return

        parentNode = n.parent
        temp3 = parentNode.keys
        for i in range(len(temp3)):
            if (temp3[i] == n):
                parentNode.values = parentNode.values[:i] + \
                    [value] + parentNode.values[i:]
                parentNode.keys = parentNode.keys[:i +
                                                  1] + [ndash] + parentNode.keys[i + 1:]
                if (len(parentNode.keys) > parentNode.order):
                    parentdash = Node(parentNode.order)
                    parentdash.parent = parentNode.parent
                    mid = int(math.ceil(parentNode.order / 2)) - 1
                    parentdash.values = parentNode.values[mid + 1:]
                    parentdash.keys = parentNode.keys[mid + 1:]
                    value_ = parentNode.values[mid]
                    if (mid == 0):
                        parentNode.values = parentNode.values[:mid + 1]
                    else:
                        parentNode.values = parentNode.values[:mid]
                    parentNode.keys = parentNode.keys[:mid + 1]
                    for j in parentNode.keys:
                        j.parent = parentNode
                    for j in parentdash.keys:
                        j.parent = parentdash
                    self.insert_in_parent(parentNode, value_, parentdash)

# Print the tree
def printTree(tree):
    lst = [tree.root]
    level = [0]
    leaf = None
    flag = 0
    lev_leaf = 0

    node1 = Node(str(level[0]) + str(tree.root.values))

    while (len(lst) != 0):
        x = lst.pop(0)
        lev = level.pop(0)
        if (x.check_leaf == False):
            for i, item in enumerate(x.keys):
                print(item.values)
        else:
            for i, item in enumerate(x.keys):
                print(item.values)
            if (flag == 0):
                lev_leaf = lev
                leaf = x
                flag = 1


record_len = 3
bplustree = BplusTree(record_len)
bplustree.insert('5', '33')
bplustree.insert('15', '21')
bplustree.insert('25', '31')
bplustree.insert('35', '41')
bplustree.insert('45', '10')

printTree(bplustree)

if(bplustree.find('5', '34')):
    print("Found")
else:
    print("Not found")

Output
['15', '25']
['35', '45']
['5']
Not found

Time Complexity: O(log n)
Auxiliary Space: O(1)

B+ Tree in Python

In computer science, data structures are crucial in efficiently managing and organizing data. Among these, the B+ tree is a powerful and important data structure, widely used in databases and file systems. In this article, we will discuss the concept of B+ trees, exploring their structure, operations, and implementation in Python.

B+ Tree in Python

Table of Content

  • What is a B+ Tree?
  • Key Characteristics of B+ Trees
  • Operations on B+ Trees
  • Searching in B+ Tree
  • Insertion in B+ Tree
  • Deletion in B+ Tree

Similar Reads

What is a B+ Tree?

A B+ tree is a self-balancing tree data structure designed for efficient storage and retrieval of data in secondary memory such as disk storage. It is a variant of the B-tree, characterized by its ability to store multiple keys in each node, with only the leaf nodes containing actual data pointers. The internal nodes act as index nodes, facilitating fast searching and traversal....

Key Characteristics of B+ Trees:

Ordered Structure: Keys in a B+ tree are stored in sorted order, enabling efficient searching through binary search.Balanced Tree: B+ trees are self-balancing, ensuring that operations such as insertion and deletion maintain a balanced tree structure, which results in optimal performance.Leaf Node Linked List: All leaf nodes are linked together, forming a linked list. This feature facilitates a range of queries and sequential access....

Operations on B+ Trees:

Search: Searching in a B+ tree involves traversing the tree from the root node to the leaf node, and performing a binary search to locate the desired key.Insertion: Inserting a new key-value pair into a B+ tree begins with a search operation to find the appropriate leaf node. If the leaf node has space, the key-value pair is inserted. Otherwise, the node is split, and the insertion is propagated upwards.Deletion: Deleting a key-value pair from a B+ tree follows a similar process to insertion. After locating the leaf node containing the key to be deleted, the key is removed. If the node becomes underflowed, it may borrow keys from sibling nodes or merge with them to maintain balance....

Searching in B+ Tree:

Searching in a B-tree involves traversing the tree from the root to find the node that might contain the desired key....

Insertion in B+ Tree:

Insertion in a B+ tree involves placing a new key-value pair into the appropriate leaf node and ensuring tree balance through splits and updates....

Deletion in B+ Tree:

Deletion in a B+ tree involves removing a key-value pair, adjusting the structure of the tree, and potentially merging or redistributing nodes to maintain B+ tree properties....

Contact Us