Launch your tech mastery with us—your coding journey starts now!
Course Content
Data Structure

B-Trees

A B-Tree is a self-balancing search tree designed for systems that read and write large blocks of data, like databases and file systems.

B-Tree data structure illustration showing nodes containing multiple keys and multiple children, organized in balanced hierarchical levels for efficient large data storage and searching.

Properties of B-Tree of order M

  1. Every node has at most M children
  2. Every non-leaf node (except root) has at least ⌈M/2⌉ children
  3. The root has at least 2 children (if it’s not a leaf)
  4. All leaves are at the same level
  5. A non-leaf node with k children contains k-1 keys

B-Tree Implementation (Order 3)

java
import java.util.ArrayList;
import java.util.List;

class BTreeNode {
    List<Integer> keys;
    int t; // Minimum degree (minimum number of keys is t-1)
    List<BTreeNode> children;
    boolean isLeaf;
    
    public BTreeNode(int t, boolean isLeaf) {
        this.t = t;
        this.isLeaf = isLeaf;
        this.keys = new ArrayList<>();
        this.children = new ArrayList<>();
    }
    
    // Search a key in subtree rooted with this node
    BTreeNode search(int key) {
        // Find the first key greater than or equal to k
        int i = 0;
        while (i < keys.size() && key > keys.get(i))
            i++;
        
        // If the found key is equal to k, return this node
        if (i < keys.size() && keys.get(i) == key)
            return this;
        
        // If key is not found and this is a leaf node
        if (isLeaf)
            return null;
        
        // Go to the appropriate child
        return children.get(i).search(key);
    }
    
    // Insert a new key in this node
    // The node must be non-full when this function is called
    void insertNonFull(int key) {
        // Initialize index as index of rightmost element
        int i = keys.size() - 1;
        
        // If this is a leaf node
        if (isLeaf) {
            // Add a new key to keys
            keys.add(0);
            
            // Find location where new key should be inserted
            while (i >= 0 && keys.get(i) > key) {
                keys.set(i + 1, keys.get(i));
                i--;
            }
            
            // Insert the new key at found location
            keys.set(i + 1, key);
        } else {
            // Find the child which is going to have the new key
            while (i >= 0 && keys.get(i) > key)
                i--;
            
            // Check if the found child is full
            if (children.get(i + 1).keys.size() == 2 * t - 1) {
                // If the child is full, split it
                splitChild(i + 1, children.get(i + 1));
                
                // After split, the middle key goes up and
                // child is split into two
                if (keys.get(i + 1) < key)
                    i++;
            }
            children.get(i + 1).insertNonFull(key);
        }
    }
    
    // Split the child y of this node
    void splitChild(int i, BTreeNode y) {
        // Create a new node to store (t-1) keys of y
        BTreeNode z = new BTreeNode(y.t, y.isLeaf);
        
        // Copy the last (t-1) keys of y to z
        for (int j = 0; j < t - 1; j++)
            z.keys.add(y.keys.get(j + t));
        
        // Copy the last t children of y to z
        if (!y.isLeaf) {
            for (int j = 0; j < t; j++)
                z.children.add(y.children.get(j + t));
        }
        
        // Reduce the number of keys in y
        y.keys.subList(t - 1, y.keys.size()).clear();
        
        // Remove last t children from y
        if (!y.isLeaf)
            y.children.subList(t, y.children.size()).clear();
        
        // Insert a new child to this node
        children.add(i + 1, z);
        
        // Move a key from y to this node
        keys.add(i, y.keys.get(t - 1));
        y.keys.remove(t - 1);
    }
    
    // Traverse all nodes in a subtree rooted with this node
    void traverse() {
        int i;
        for (i = 0; i < keys.size(); i++) {
            // If this is not leaf, traverse the subtree before key[i]
            if (!isLeaf)
                children.get(i).traverse();
            System.out.print(keys.get(i) + " ");
        }
        
        // Print the subtree rooted with last child
        if (!isLeaf)
            children.get(i).traverse();
    }
}

class BTree {
    BTreeNode root;
    int t; // Minimum degree
    
    public BTree(int t) {
        this.root = null;
        this.t = t;
    }
    
    // Search a key in this tree
    BTreeNode search(int key) {
        return (root == null) ? null : root.search(key);
    }
    
    // Insert a new key
    void insert(int key) {
        // If tree is empty
        if (root == null) {
            root = new BTreeNode(t, true);
            root.keys.add(key);
        } else {
            // If root is full, tree grows in height
            if (root.keys.size() == 2 * t - 1) {
                BTreeNode s = new BTreeNode(t, false);
                
                // Make old root as child of new root
                s.children.add(root);
                
                // Split the old root and move 1 key to the new root
                s.splitChild(0, root);
                
                // New root has two children now.
                // Decide which of the two children is going to have new key
                int i = 0;
                if (s.keys.get(0) < key)
                    i++;
                s.children.get(i).insertNonFull(key);
                
                // Change root
                root = s;
            } else
                root.insertNonFull(key);
        }
    }
    
    // Traverse the tree
    void traverse() {
        if (root != null)
            root.traverse();
        System.out.println();
    }
    
    public static void main(String[] args) {
        BTree t = new BTree(3); // A B-Tree with minimum degree 3
        
        System.out.println("Inserting elements: 10, 20, 5, 6, 12, 30, 7, 17");
        t.insert(10);
        t.insert(20);
        t.insert(5);
        t.insert(6);
        t.insert(12);
        t.insert(30);
        t.insert(7);
        t.insert(17);
        
        System.out.println("Traversal of the constructed tree:");
        t.traverse();
        
        int k = 6;
        BTreeNode result = t.search(k);
        System.out.println("\nSearch for key " + k + ": " + 
                          (result != null ? "Found" : "Not Found"));
        
        k = 15;
        result = t.search(k);
        System.out.println("Search for key " + k + ": " + 
                          (result != null ? "Found" : "Not Found"));
    }
}
```

**Output:**
```
Inserting elements: 10, 20, 5, 6, 12, 30, 7, 17
Traversal of the constructed tree:
5 6 7 10 12 17 20 30 

Search for key 6: Found
Search for key 15: Not Found

Simplified B-Tree Example (Order 3)

java
class SimpleBTree {
    
    static class Node {
        int n; // Current number of keys
        int[] keys = new int[3]; // Maximum 2 keys for order 3
        Node[] children = new Node[4]; // Maximum 3 children
        boolean isLeaf;
        
        Node(boolean isLeaf) {
            this.isLeaf = isLeaf;
            this.n = 0;
        }
        
        void display(String prefix, boolean isTail) {
            System.out.print(prefix + (isTail ? "└── " : "├── "));
            System.out.print("[");
            for (int i = 0; i < n; i++) {
                System.out.print(keys[i]);
                if (i < n - 1) System.out.print(", ");
            }
            System.out.println("]");
            
            if (!isLeaf) {
                for (int i = 0; i <= n; i++) {
                    if (children[i] != null) {
                        children[i].display(
                            prefix + (isTail ? "    " : "│   "), 
                            i == n
                        );
                    }
                }
            }
        }
    }
    
    Node root;
    
    SimpleBTree() {
        root = new Node(true);
    }
    
    void display() {
        if (root != null) {
            System.out.println("B-Tree Structure:");
            root.display("", true);
        }
    }
    
    public static void main(String[] args) {
        SimpleBTree tree = new SimpleBTree();
        
        // Manually creating a simple B-Tree for demonstration
        tree.root = new Node(false);
        tree.root.keys[0] = 30;
        tree.root.n = 1;
        
        tree.root.children[0] = new Node(true);
        tree.root.children[0].keys[0] = 10;
        tree.root.children[0].keys[1] = 20;
        tree.root.children[0].n = 2;
        
        tree.root.children[1] = new Node(true);
        tree.root.children[1].keys[0] = 40;
        tree.root.children[1].keys[1] = 50;
        tree.root.children[1].n = 2;
        
        tree.display();
    }
}