Algorithm
In a B-tree, deletion is a complex operation that involves several steps to maintain the properties of the B-tree. B-trees are self-balancing search trees, commonly used in databases and file systems, where each node can have multiple keys and child pointers. The steps for deletion in a B-tree generally include:
-
Search for the Key: Start at the root and traverse the tree to find the node containing the key to be deleted. If the key is not present in the tree, the deletion operation stops.
-
Delete the Key: Once the key is found in a node, delete it. If the node is an internal node, the key can be simply removed. If the node is a leaf, remove the key and handle the deletion according to the type of node.
-
Handle Underflow: Deleting a key from a node may cause underflow (a violation of the minimum number of keys constraint) in that node. If underflow occurs, borrow a key from a neighboring sibling or merge with a sibling.
-
Recursively Delete in the Parent: After deleting a key and handling underflow, if the parent node becomes underflowed, repeat the process by deleting the key in the parent node and handling underflow there as well. This recursive process continues until the root is reached.
-
Update Parent Keys: As you go up the tree, update the keys in the parent nodes to reflect changes in the child nodes.
-
Adjust Root: If the root becomes underflowed during the deletion process, adjust the root to be the only remaining child.
The specific details of how underflow is handled (borrowing or merging with siblings) and the exact rules for updating keys depend on the variant of B-tree (e.g., B-tree, B+ tree) and the specific implementation.
Code Examples
#1 Deletion from a B-tree implement in Python
Code -
Python Programming
class BTreeNode:
def __init__(self, leaf=True):
self.keys = []
self.children = []
self.leaf = leaf
class BTree:
def __init__(self, t):
self.root = BTreeNode()
self.t = t
def insert(self, key):
root = self.root
if len(root.keys) == (2 * self.t) - 1:
new_root = BTreeNode()
new_root.children.append(self.root)
self.split(new_root, 0)
self.root = new_root
self._insert(self.root, key)
def _insert(self, node, key):
index = len(node.keys) - 1
if node.leaf:
node.keys.append(0) # Make space for the new key
while index >= 0 and key < node.keys[index]:
node.keys[index + 1] = node.keys[index]
index -= 1
node.keys[index + 1] = key
else:
while index >= 0 and key < node.keys[index]:
index -= 1
index += 1
if len(node.children[index].keys) == (2 * self.t) - 1:
self.split(node, index)
if key > node.keys[index]:
index += 1
self._insert(node.children[index], key)
def split(self, parent, index):
t = self.t
child = parent.children[index]
new_child = BTreeNode(leaf=child.leaf)
parent.keys.insert(index, child.keys[t - 1])
parent.children.insert(index + 1, new_child)
new_child.keys = child.keys[t:2 * t - 1]
child.keys = child.keys[:t - 1]
if not child.leaf:
new_child.children = child.children[t:]
child.children = child.children[:t]
def delete(self, key):
self._delete(self.root, key)
def _delete(self, node, key):
index = 0
while index < len(node.keys) and key > node.keys[index]:
index += 1
if node.leaf:
if key in node.keys:
node.keys.remove(key)
else:
print(f"Key {key} not found.")
else:
child = node.children[index]
if len(child.keys) >= self.t:
self._delete(child, key)
elif index > 0 and len(node.children[index - 1].keys) >= self.t:
self.borrowFromPrev(node, index)
elif index < len(node.children) - 1 and len(node.children[index + 1].keys) >= self.t:
self.borrowFromNext(node, index)
elif index > 0:
self.merge(node, index - 1)
self._delete(node.children[index - 1], key)
else:
self.merge(node, index)
self._delete(node.children[index], key)
def borrowFromPrev(self, node, index):
child = node.children[index]
sibling = node.children[index - 1]
child.keys.insert(0, node.keys[index - 1])
node.keys[index - 1] = sibling.keys.pop()
if not child.leaf:
child.children.insert(0, sibling.children.pop())
def borrowFromNext(self, node, index):
child = node.children[index]
sibling = node.children[index + 1]
child.keys.append(node.keys[index])
node.keys[index] = sibling.keys.pop(0)
if not child.leaf:
child.children.append(sibling.children.pop(0))
def merge(self, node, index):
child = node.children[index]
sibling = node.children[index + 1]
child.keys.append(node.keys.pop(index))
child.keys.extend(sibling.keys)
if not child.leaf:
child.children.extend(sibling.children)
node.children.pop(index + 1)
# Example usage:
b_tree = BTree(t=3)
keys_to_insert = [3, 7, 1, 8, 5, 12, 9, 6, 11, 2, 4, 10]
for key in keys_to_insert:
b_tree.insert(key)
print("B-tree after insertion:")
# Display the tree structure (you may want to customize this based on your needs)
print("Root:", b_tree.root.keys)
for i, child in enumerate(b_tree.root.children):
print(f"Child {i}:", child.keys)
key_to_delete = 6
b_tree.delete(key_to_delete)
print(f"\nB-tree after deleting key {key_to_delete}:")
print("Root:", b_tree.root.keys)
for i, child in enumerate(b_tree.root.children):
print(f"Child {i}:", child.keys)
Copy The Code &
Try With Live Editor
#2 Deletion from a B-tree implement in Java
Code -
Java Programming
To implement deletion in a B-tree in Java, you need to follow a series of steps to maintain the properties of the B-tree while removing a key. Here's a basic outline of how you might approach this task:
Search for the Key:
Start at the root and traverse the tree to find the node containing the key to be deleted.
If the key is not present, the deletion operation is complete.
Delete Key from Node:
If the key is in a leaf node, simply remove it.
If the key is in an internal node, you need to handle this case differently. You can replace the key with its predecessor or successor from the left or right subtree.
Handle Underflow:
After deletion, check if the node underflows (i.e., has fewer keys than the minimum required).
If underflow occurs, borrow a key from a neighboring node, redistribute keys, or merge nodes to maintain the B-tree properties.
Recursively Delete in Child Nodes:
If you have merged or borrowed keys, and the parent node is underflowed, apply the same steps recursively.
Update Root:
If the root node becomes empty after deletion, update the root to be its only child.
Copy The Code &
Try With Live Editor
#3 Deletion from a B-tree implement in C
Code -
C Programming
Assuming you have a B-tree node structure defined as follows:
// B-tree node structure
typedef struct BTreeNode {
int *keys; // Array to store keys
struct BTreeNode **children; // Array to store child pointers
int n; // Current number of keys
int leaf; // 1 if node is a leaf, 0 otherwise
} BTreeNode;
< /code>
And a B-tree structure:
// B-tree structure
typedef struct BTree {
BTreeNode *root;
int t; // Minimum degree
} BTree;
< /code>
Here is a high-level C implementation of the B-tree deletion operation:
#include <stdio.h>
#include <stdlib.h>
// Assume other B-tree functions (e.g., search, insert) are implemented
// Function to delete a key from the B-tree
void deleteKey(BTreeNode *root, int key) {
if (!root) {
printf("The tree is empty.\n");
return;
}
// Perform deletion
// Implementation details will depend on the specific B-tree deletion algorithm
// Example: Call a delete function based on the B-tree type (e.g., B-tree, B+ tree)
deleteKeyInBTree(root, key);
}
// Function to delete a key from a B-tree node
void deleteKeyInBTree(BTreeNode *node, int key) {
// Implementation details will depend on the specific B-tree deletion algorithm
// Example: Handle deletion based on whether the node is a leaf or not
if (node->leaf) {
// Handle deletion in a leaf node
deleteKeyInLeaf(node, key);
} else {
// Handle deletion in an internal node
deleteKeyInInternalNode(node, key);
}
}
// Function to delete a key from a leaf node
void deleteKeyInLeaf(BTreeNode *node, int key) {
// Implementation details will depend on the specific B-tree deletion algorithm
// Example: Implement deletion in a leaf node
}
// Function to delete a key from an internal node
void deleteKeyInInternalNode(BTreeNode *node, int key) {
// Implementation details will depend on the specific B-tree deletion algorithm
// Example: Implement deletion in an internal node
}
int main() {
// Example usage
BTree *tree = createBTree(3); // Assume B-tree with minimum degree 3
// Insert keys into the B-tree
insertKey(tree, 10);
insertKey(tree, 20);
insertKey(tree, 5);
insertKey(tree, 6);
insertKey(tree, 12);
insertKey(tree, 30);
insertKey(tree, 7);
insertKey(tree, 17);
// Print the B-tree
printf("B-tree before deletion:\n");
printBTree(tree->root);
// Delete a key from the B-tree
int keyToDelete = 6;
deleteKey(tree->root, keyToDelete);
// Print the B-tree after deletion
printf("\nB-tree after deletion of key %d:\n", keyToDelete);
printBTree(tree->root);
return 0;
}
Copy The Code &
Try With Live Editor
#4 Deletion from a B-tree implement in C++
Code -
C++ Programming
#include <iostream>
const int MIN_KEYS = 1; // Minimum number of keys for a node
struct Node {
int *keys;
Node **children;
bool isLeaf;
int numKeys;
};
class BTree {
private:
Node *root;
// Helper function to search for a key in a node
int findKeyIndex(Node *node, int key) {
int index = 0;
while (index < node->numKeys && key > node->keys[index]) {
++index;
}
return index;
}
// Helper function to borrow a key from the predecessor
void borrowFromPrev(Node *node, int index) {
Node *child = node->children[index];
Node *sibling = node->children[index - 1];
for (int i = child->numKeys - 1; i >= 0; --i) {
child->keys[i + 1] = child->keys[i];
}
if (!child->isLeaf) {
for (int i = child->numKeys; i >= 0; --i) {
child->children[i + 1] = child->children[i];
}
}
child->keys[0] = node->keys[index - 1];
if (!child->isLeaf) {
child->children[0] = sibling->children[sibling->numKeys];
}
node->keys[index - 1] = sibling->keys[sibling->numKeys - 1];
child->numKeys += 1;
sibling->numKeys -= 1;
}
// Helper function to borrow a key from the successor
void borrowFromNext(Node *node, int index) {
Node *child = node->children[index];
Node *sibling = node->children[index + 1];
child->keys[child->numKeys] = node->keys[index];
if (!child->isLeaf) {
child->children[child->numKeys + 1] = sibling->children[0];
}
node->keys[index] = sibling->keys[0];
for (int i = 1; i < sibling->numKeys; ++i) {
sibling->keys[i - 1] = sibling->keys[i];
}
if (!sibling->isLeaf) {
for (int i = 1; i < = sibling->numKeys; ++i) {
sibling->children[i - 1] = sibling->children[i];
}
}
child->numKeys += 1;
sibling->numKeys -= 1;
}
// Helper function to merge a child with its sibling
void merge(Node *node, int index) {
Node *child = node->children[index];
Node *sibling = node->children[index + 1];
child->keys[MIN_KEYS - 1] = node->keys[index];
for (int i = 0; i < sibling->numKeys; ++i) {
child->keys[i + MIN_KEYS] = sibling->keys[i];
}
if (!child->isLeaf) {
for (int i = 0; i < = sibling->numKeys; ++i) {
child->children[i + MIN_KEYS] = sibling->children[i];
}
}
for (int i = index + 1; i < node->numKeys; ++i) {
node->keys[i - 1] = node->keys[i];
}
for (int i = index + 2; i < = node->numKeys; ++i) {
node->children[i - 1] = node->children[i];
}
child->numKeys += sibling->numKeys + 1;
node->numKeys -= 1;
delete sibling;
}
// Helper function to delete a key from a node
void removeFromNode(Node *node, int index) {
if (node->isLeaf) {
for (int i = index + 1; i < node->numKeys; ++i) {
node->keys[i - 1] = node->keys[i];
}
node->numKeys -= 1;
} else {
Node *child = node->children[index];
Node *successor = node->children[index + 1];
if (child->numKeys >= MIN_KEYS) {
int predecessorKey = getPredecessor(child);
removeFromNode(child, findKeyIndex(child, predecessorKey));
node->keys[index] = predecessorKey;
} else if (successor->numKeys >= MIN_KEYS) {
int successorKey = getSuccessor(successor);
removeFromNode(successor, findKeyIndex(successor, successorKey));
node->keys[index] = successorKey;
} else {
merge(node, index);
removeFromNode(child, MIN_KEYS - 1);
}
}
}
// Helper function to get the predecessor key
int getPredecessor(Node *node) {
while (!node->isLeaf) {
node = node->children[node->numKeys];
}
return node->keys[node->numKeys - 1];
}
// Helper function to get the successor key
int getSuccessor(Node *node) {
while (!node->isLeaf) {
node = node->children[0];
}
return node->keys[0];
}
// Helper function to delete a key from the B-tree
void deleteKey(Node *node, int key) {
int index = findKeyIndex(node, key);
if (index < node->numKeys && node->keys[index] == key) {
removeFromNode(node, index);
} else {
if (node->isLeaf) {
std::cout << "Key " << key << " not found in the tree.\n";
return;
}
bool isLastChild = (index == node->numKeys);
if (node->children[index]->numKeys < MIN_KEYS) {
fill(node, index);
}
if (isLastChild && index > node->numKeys) {
deleteKey(node->children[index - 1], key);
} else {
deleteKey(node->children[index], key);
}
}
}
// Helper function to fill a child that has less than MIN_KEYS keys
void fill(Node *node, int index) {
if (index != 0 && node->children[index - 1]->numKeys >= MIN_KEYS) {
borrowFromPrev(node, index);
} else if (index != node->numKeys && node->children[index + 1]->numKeys >= MIN_KEYS) {
borrowFromNext(node, index);
} else {
if (index != node->numKeys) {
merge(node, index);
} else {
merge(node, index - 1);
}
}
}
public:
BTree() : root(nullptr) {}
// Function to delete a key from the B-tree
void deleteKey(int key) {
Copy The Code &
Try With Live Editor
Demonstration
Deletion from a B-tree-DevsEnv