Open In App

Delete Operation in B-Tree

Last Updated : 23 Jul, 2025
Comments
Improve
Suggest changes
31 Likes
Like
Report

A B Tree is a type of data structure commonly known as a Balanced Tree that stores multiple data items very easily. B Trees are one of the most useful data structures that provide ordered access to the data in the database. In this article, we will see the delete operation in the B-Tree. B-Trees are self-balancing trees.

Deletion Process in B-Trees

Deletion from a B-tree is more complicated than insertion because we can delete a key from any node-not just a leaf—and when we delete a key from an internal node, we will have to rearrange the node’s children. 

As in insertion, we must make sure the deletion doesn't violate the B-tree properties. Just as we had to ensure that a node didn't get too big due to insertion, we must ensure that a node doesn't get too small during deletion (except that the root is allowed to have fewer than the minimum number t-1 of keys). Just as a simple insertion algorithm might have to back up if a node on the path to where the key was to be inserted was full, a simple approach to deletion might have to back up if a node (other than the root) along the path to where the key is to be deleted has the minimum number of keys.

The deletion procedure deletes the key k from the subtree rooted at x. This procedure guarantees that whenever it calls itself recursively on a node x, the number of keys in x is at least the minimum degree t. Note that this condition requires one more key than the minimum required by the usual B-tree conditions, so sometimes a key may have to be moved into a child node before recursion descends to that child. This strengthened condition allows us to delete a key from the tree in one downward pass without having to "back up" (with one exception, which we’ll explain). You should interpret the following specification for deletion from a B-tree with the understanding that if the root node x ever becomes an internal node having no keys (this situation can occur in cases 2c and 3b then we delete x, and x’s only child x.c1 becomes the new root of the tree, decreasing the height of the tree by one and preserving the property that the root of the tree contains at least one key (unless the tree is empty).

Various Cases of Deletion

Case 1: If the key k is in node x and x is a leaf, delete the key k from x.

Case 2: If the key k is in node x and x is an internal node, do the following.

  • If the child y that precedes k in node x has at least t keys, then find the predecessor k0 of k in the sub-tree rooted at y. Recursively delete k0, and replace k with k0 in x. (We can find k0 and delete it in a single downward pass.)
  • If y has fewer than t keys, then, symmetrically, examine the child z that follows k in node x. If z has at least t keys, then find the successor k0 of k in the subtree rooted at z. Recursively delete k0, and replace k with k0 in x. (We can find k0 and delete it in a single downward pass.)
  • Otherwise, if both y and z have only t-1 keys, merge k and all of z into y, so that x loses both k and the pointer to z, and y now contains 2t-1 keys. Then free z and recursively delete k from y.

Case 3: If the key k is not present in internal node x, determine the root x.c(i) of the appropriate subtree that must contain k, if k is in the tree at all. If x.c(i) has only t-1 keys, execute steps 3a or 3b as necessary to guarantee that we descend to a node containing at least t keys. Then finish by recursing on the appropriate child of x.

  • If x.c(i) has only t-1 keys but has an immediate sibling with at least t keys, give x.c(i) an extra key by moving a key from x down into x.c(i), moving a key from x.c(i) ’s immediate left or right sibling up into x, and moving the appropriate child pointer from the sibling into x.c(i).
  • If x.c(i) and both of x.c(i)'s immediate siblings have t-1 keys, merge x.c(i) with one sibling, which involves moving a key from x down into the new merged node to become the median key for that node.

Since most of the keys in a B-tree are in the leaves, deletion operations are most often used to delete keys from leaves. The recursive delete procedure then acts in one downward pass through the tree, without having to back up. When deleting a key in an internal node, however, the procedure makes a downward pass through the tree but may have to return to the node from which the key was deleted to replace the key with its predecessor or successor (cases 2a and 2b).

The following figures explain the deletion process. 

Deletion Operation in B+ Trees
Deletion Operation in B+ Trees

The next processes are shown below in the figure.

Deletion Operation in B+ Trees

Implementation

Following is the implementation of the deletion process.

C++
#include<iostream> using namespace std; // A BTree node class BTreeNode {  int *keys; // An array of keys  int t; // Minimum degree (defines the range for number of keys)  BTreeNode **C; // An array of child pointers  int n; // Current number of keys  bool leaf; // Is true when node is leaf. Otherwise false public:  BTreeNode(int _t, bool _leaf); // Constructor  // A function to traverse all nodes in a subtree rooted with this node  void traverse();  // A function to search a key in subtree rooted with this node.  BTreeNode *search(int k); // returns NULL if k is not present.  // A function that returns the index of the first key that is greater  // or equal to k  int findKey(int k);  // A utility function to insert a new key in the subtree rooted with  // this node. The assumption is, the node must be non-full when this  // function is called  void insertNonFull(int k);  // A utility function to split the child y of this node. i is index  // of y in child array C[]. The Child y must be full when this  // function is called  void splitChild(int i, BTreeNode *y);  // A wrapper function to remove the key k in subtree rooted with  // this node.  void remove(int k);  // A function to remove the key present in idx-th position in  // this node which is a leaf  void removeFromLeaf(int idx);  // A function to remove the key present in idx-th position in  // this node which is a non-leaf node  void removeFromNonLeaf(int idx);  // A function to get the predecessor of the key- where the key  // is present in the idx-th position in the node  int getPred(int idx);  // A function to get the successor of the key- where the key  // is present in the idx-th position in the node  int getSucc(int idx);  // A function to fill up the child node present in the idx-th  // position in the C[] array if that child has less than t-1 keys  void fill(int idx);  // A function to borrow a key from the C[idx-1]-th node and place  // it in C[idx]th node  void borrowFromPrev(int idx);  // A function to borrow a key from the C[idx+1]-th node and place it  // in C[idx]th node  void borrowFromNext(int idx);  // A function to merge idx-th child of the node with (idx+1)th child of  // the node  void merge(int idx);  // Make BTree friend of this so that we can access private members of  // this class in BTree functions  friend class BTree; }; class BTree {  BTreeNode *root; // Pointer to root node  int t; // Minimum degree public:  // Constructor (Initializes tree as empty)  BTree(int _t)  {  root = NULL;  t = _t;  }  void traverse()  {  if (root != NULL) root->traverse();  }  // function to search a key in this tree  BTreeNode* search(int k)  {  return (root == NULL)? NULL : root->search(k);  }  // The main function that inserts a new key in this B-Tree  void insert(int k);  // The main function that removes a new key in this B-Tree  void remove(int k); }; BTreeNode::BTreeNode(int t1, bool leaf1) {  // Copy the given minimum degree and leaf property  t = t1;  leaf = leaf1;  // Allocate memory for maximum number of possible keys  // and child pointers  keys = new int[2*t-1];  C = new BTreeNode *[2*t];  // Initialize the number of keys as 0  n = 0; } // A utility function that returns the index of the first key that is // greater than or equal to k int BTreeNode::findKey(int k) {  int idx=0;  while (idx<n && keys[idx] < k)  ++idx;  return idx; } // A function to remove the key k from the sub-tree rooted with this node void BTreeNode::remove(int k) {  int idx = findKey(k);  // The key to be removed is present in this node  if (idx < n && keys[idx] == k)  {  // If the node is a leaf node - removeFromLeaf is called  // Otherwise, removeFromNonLeaf function is called  if (leaf)  removeFromLeaf(idx);  else  removeFromNonLeaf(idx);  }  else  {  // If this node is a leaf node, then the key is not present in tree  if (leaf)  {  cout<<"The key "<<k<<" is does not exist in the tree\n";  return;  }  // The key to be removed is present in the sub-tree rooted with this node  // The flag indicates whether the key is present in the sub-tree rooted  // with the last child of this node  bool flag = ( (idx==n)? true : false );  // If the child where the key is supposed to exist has less that t keys,  // we fill that child  if (C[idx]->n < t)  fill(idx);  // If the last child has been merged, it must have merged with the previous  // child and so we recurse on the (idx-1)th child. Else, we recurse on the  // (idx)th child which now has atleast t keys  if (flag && idx > n)  C[idx-1]->remove(k);  else  C[idx]->remove(k);  }  return; } // A function to remove the idx-th key from this node - which is a leaf node void BTreeNode::removeFromLeaf (int idx) {  // Move all the keys after the idx-th pos one place backward  for (int i=idx+1; i<n; ++i)  keys[i-1] = keys[i];  // Reduce the count of keys  n--;  return; } // A function to remove the idx-th key from this node - which is a non-leaf node void BTreeNode::removeFromNonLeaf(int idx) {  int k = keys[idx];  // If the child that precedes k (C[idx]) has atleast t keys,  // find the predecessor 'pred' of k in the subtree rooted at  // C[idx]. Replace k by pred. Recursively delete pred  // in C[idx]  if (C[idx]->n >= t)  {  int pred = getPred(idx);  keys[idx] = pred;  C[idx]->remove(pred);  }  // If the child C[idx] has less that t keys, examine C[idx+1].  // If C[idx+1] has atleast t keys, find the successor 'succ' of k in  // the subtree rooted at C[idx+1]  // Replace k by succ  // Recursively delete succ in C[idx+1]  else if (C[idx+1]->n >= t)  {  int succ = getSucc(idx);  keys[idx] = succ;  C[idx+1]->remove(succ);  }  // If both C[idx] and C[idx+1] has less that t keys,merge k and all of C[idx+1]  // into C[idx]  // Now C[idx] contains 2t-1 keys  // Free C[idx+1] and recursively delete k from C[idx]  else  {  merge(idx);  C[idx]->remove(k);  }  return; } // A function to get predecessor of keys[idx] int BTreeNode::getPred(int idx) {  // Keep moving to the right most node until we reach a leaf  BTreeNode *cur=C[idx];  while (!cur->leaf)  cur = cur->C[cur->n];  // Return the last key of the leaf  return cur->keys[cur->n-1]; } int BTreeNode::getSucc(int idx) {  // Keep moving the left most node starting from C[idx+1] until we reach a leaf  BTreeNode *cur = C[idx+1];  while (!cur->leaf)  cur = cur->C[0];  // Return the first key of the leaf  return cur->keys[0]; } // A function to fill child C[idx] which has less than t-1 keys void BTreeNode::fill(int idx) {  // If the previous child(C[idx-1]) has more than t-1 keys, borrow a key  // from that child  if (idx!=0 && C[idx-1]->n>=t)  borrowFromPrev(idx);  // If the next child(C[idx+1]) has more than t-1 keys, borrow a key  // from that child  else if (idx!=n && C[idx+1]->n>=t)  borrowFromNext(idx);  // Merge C[idx] with its sibling  // If C[idx] is the last child, merge it with its previous sibling  // Otherwise merge it with its next sibling  else  {  if (idx != n)  merge(idx);  else  merge(idx-1);  }  return; } // A function to borrow a key from C[idx-1] and insert it // into C[idx] void BTreeNode::borrowFromPrev(int idx) {  BTreeNode *child=C[idx];  BTreeNode *sibling=C[idx-1];  // The last key from C[idx-1] goes up to the parent and key[idx-1]  // from parent is inserted as the first key in C[idx]. Thus, the loses  // sibling one key and child gains one key  // Moving all key in C[idx] one step ahead  for (int i=child->n-1; i>=0; --i)  child->keys[i+1] = child->keys[i];  // If C[idx] is not a leaf, move all its child pointers one step ahead  if (!child->leaf)  {  for(int i=child->n; i>=0; --i)  child->C[i+1] = child->C[i];  }  // Setting child's first key equal to keys[idx-1] from the current node  child->keys[0] = keys[idx-1];  // Moving sibling's last child as C[idx]'s first child  if(!child->leaf)  child->C[0] = sibling->C[sibling->n];  // Moving the key from the sibling to the parent  // This reduces the number of keys in the sibling  keys[idx-1] = sibling->keys[sibling->n-1];  child->n += 1;  sibling->n -= 1;  return; } // A function to borrow a key from the C[idx+1] and place // it in C[idx] void BTreeNode::borrowFromNext(int idx) {  BTreeNode *child=C[idx];  BTreeNode *sibling=C[idx+1];  // keys[idx] is inserted as the last key in C[idx]  child->keys[(child->n)] = keys[idx];  // Sibling's first child is inserted as the last child  // into C[idx]  if (!(child->leaf))  child->C[(child->n)+1] = sibling->C[0];  //The first key from sibling is inserted into keys[idx]  keys[idx] = sibling->keys[0];  // Moving all keys in sibling one step behind  for (int i=1; i<sibling->n; ++i)  sibling->keys[i-1] = sibling->keys[i];  // Moving the child pointers one step behind  if (!sibling->leaf)  {  for(int i=1; i<=sibling->n; ++i)  sibling->C[i-1] = sibling->C[i];  }  // Increasing and decreasing the key count of C[idx] and C[idx+1]  // respectively  child->n += 1;  sibling->n -= 1;  return; } // A function to merge C[idx] with C[idx+1] // C[idx+1] is freed after merging void BTreeNode::merge(int idx) {  BTreeNode *child = C[idx];  BTreeNode *sibling = C[idx+1];  // Pulling a key from the current node and inserting it into (t-1)th  // position of C[idx]  child->keys[t-1] = keys[idx];  // Copying the keys from C[idx+1] to C[idx] at the end  for (int i=0; i<sibling->n; ++i)  child->keys[i+t] = sibling->keys[i];  // Copying the child pointers from C[idx+1] to C[idx]  if (!child->leaf)  {  for(int i=0; i<=sibling->n; ++i)  child->C[i+t] = sibling->C[i];  }  // Moving all keys after idx in the current node one step before -  // to fill the gap created by moving keys[idx] to C[idx]  for (int i=idx+1; i<n; ++i)  keys[i-1] = keys[i];  // Moving the child pointers after (idx+1) in the current node one  // step before  for (int i=idx+2; i<=n; ++i)  C[i-1] = C[i];  // Updating the key count of child and the current node  child->n += sibling->n+1;  n--;  // Freeing the memory occupied by sibling  delete(sibling);  return; } // The main function that inserts a new key in this B-Tree void BTree::insert(int k) {  // If tree is empty  if (root == NULL)  {  // Allocate memory for root  root = new BTreeNode(t, true);  root->keys[0] = k; // Insert key  root->n = 1; // Update number of keys in root  }  else // If tree is not empty  {  // If root is full, then tree grows in height  if (root->n == 2*t-1)  {  // Allocate memory for new root  BTreeNode *s = new BTreeNode(t, false);  // Make old root as child of new root  s->C[0] = 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[0] < k)  i++;  s->C[i]->insertNonFull(k);  // Change root  root = s;  }  else // If root is not full, call insertNonFull for root  root->insertNonFull(k);  } } // A utility function to insert a new key in this node // The assumption is, the node must be non-full when this // function is called void BTreeNode::insertNonFull(int k) {  // Initialize index as index of rightmost element  int i = n-1;  // If this is a leaf node  if (leaf == true)  {  // The following loop does two things  // a) Finds the location of new key to be inserted  // b) Moves all greater keys to one place ahead  while (i >= 0 && keys[i] > k)  {  keys[i+1] = keys[i];  i--;  }  // Insert the new key at found location  keys[i+1] = k;  n = n+1;  }  else // If this node is not leaf  {  // Find the child which is going to have the new key  while (i >= 0 && keys[i] > k)  i--;  // See if the found child is full  if (C[i+1]->n == 2*t-1)  {  // If the child is full, then split it  splitChild(i+1, C[i+1]);  // After split, the middle key of C[i] goes up and  // C[i] is splitted into two. See which of the two  // is going to have the new key  if (keys[i+1] < k)  i++;  }  C[i+1]->insertNonFull(k);  } } // A utility function to split the child y of this node // Note that y must be full when this function is called void BTreeNode::splitChild(int i, BTreeNode *y) {  // Create a new node which is going to store (t-1) keys  // of y  BTreeNode *z = new BTreeNode(y->t, y->leaf);  z->n = t - 1;  // Copy the last (t-1) keys of y to z  for (int j = 0; j < t-1; j++)  z->keys[j] = y->keys[j+t];  // Copy the last t children of y to z  if (y->leaf == false)  {  for (int j = 0; j < t; j++)  z->C[j] = y->C[j+t];  }  // Reduce the number of keys in y  y->n = t - 1;  // Since this node is going to have a new child,  // create space of new child  for (int j = n; j >= i+1; j--)  C[j+1] = C[j];  // Link the new child to this node  C[i+1] = z;  // A key of y will move to this node. Find location of  // new key and move all greater keys one space ahead  for (int j = n-1; j >= i; j--)  keys[j+1] = keys[j];  // Copy the middle key of y to this node  keys[i] = y->keys[t-1];  // Increment count of keys in this node  n = n + 1; } // Function to traverse all nodes in a subtree rooted with this node void BTreeNode::traverse() {  // There are n keys and n+1 children, traverse through n keys  // and first n children  int i;  for (i = 0; i < n; i++)  {  // If this is not leaf, then before printing key[i],  // traverse the subtree rooted with child C[i].  if (leaf == false)  C[i]->traverse();  cout << " " << keys[i];  }  // Print the subtree rooted with last child  if (leaf == false)  C[i]->traverse(); } // Function to search key k in subtree rooted with this node BTreeNode *BTreeNode::search(int k) {  // Find the first key greater than or equal to k  int i = 0;  while (i < n && k > keys[i])  i++;  // If the found key is equal to k, return this node  if (keys[i] == k)  return this;  // If key is not found here and this is a leaf node  if (leaf == true)  return NULL;  // Go to the appropriate child  return C[i]->search(k); } void BTree::remove(int k) {  if (!root)  {  cout << "The tree is empty\n";  return;  }  // Call the remove function for root  root->remove(k);  // If the root node has 0 keys, make its first child as the new root  // if it has a child, otherwise set root as NULL  if (root->n==0)  {  BTreeNode *tmp = root;  if (root->leaf)  root = NULL;  else  root = root->C[0];  // Free the old root  delete tmp;  }  return; } // Driver program to test above functions int main() {  BTree t(3); // A B-Tree with minimum degree 3  t.insert(10);  t.insert(5);  t.insert(15);  t.insert(2);  t.insert(7);  t.insert(12);  t.insert(20);  cout << "Before Deletion:";  t.traverse();  cout << endl;  t.remove(5);  cout << "After Deletion:";  t.traverse();  cout << endl;  return 0; } 
Java
// A BTree node class BTreeNode {  int[] keys; // An array of keys  int t; // Minimum degree (defines the range for number of keys)  BTreeNode[] C; // An array of child pointers  int n; // Current number of keys  boolean leaf; // Is true when node is leaf. Otherwise false  public BTreeNode(int _t, boolean _leaf) { // Constructor  t = _t;  leaf = _leaf;  keys = new int[2 * t - 1];  C = new BTreeNode[2 * t];  n = 0;  }  // A function to traverse all nodes in a subtree rooted with this node  public void traverse() {  for (int i = 0; i < n; i++) {  if (!leaf) C[i].traverse();  System.out.print(" " + keys[i]);  }  if (!leaf) C[n].traverse();  }  // A function to search a key in subtree rooted with this node.  public BTreeNode search(int k) { // returns NULL if k is not present.  int i = 0;  while (i < n && k > keys[i]) i++;  if (i < n && keys[i] == k) return this;  if (leaf) return null;  return C[i].search(k);  }  // Other methods omitted for brevity... } class BTree {  BTreeNode root; // Pointer to root node  int t; // Minimum degree  public BTree(int _t) {  root = null;  t = _t;  }  public void traverse() {  if (root != null) root.traverse();  }  // Other methods omitted for brevity... } // Driver program to test above functions public class Main {  public static void main(String[] args) {  BTree t = new BTree(3); // A B-Tree with minimum degree 3  t.insert(10);  t.insert(5);  t.insert(15);  t.insert(2);  t.insert(7);  t.insert(12);  t.insert(20);  System.out.println("Before Deletion:");  t.traverse();  System.out.println();  t.remove(5);  System.out.println("After Deletion:");  t.traverse();  System.out.println();  } } 
Python
class BTreeNode: def __init__(self, t, leaf): # Constructor for BTreeNode self.t = t # Minimum degree (defines the range for the number of keys) self.leaf = leaf # Is true when the node is leaf, otherwise false self.keys = [0] * (2 * t - 1) # An array of keys self.C = [None] * (2 * t) # An array of child pointers self.n = 0 # Current number of keys def find_key(self, k): # A utility function to find the index of the first key greater than or equal to k idx = 0 while idx < self.n and self.keys[idx] < k: idx += 1 return idx def remove(self, k): # A function to remove key k from the sub-tree rooted with this node idx = self.find_key(k) if idx < self.n and self.keys[idx] == k: if self.leaf: self.remove_from_leaf(idx) else: self.remove_from_non_leaf(idx) else: if self.leaf: print(f"The key {k} does not exist in the tree") return flag = idx == self.n if self.C[idx].n < self.t: self.fill(idx) if flag and idx > self.n: self.C[idx - 1].remove(k) else: self.C[idx].remove(k) def remove_from_leaf(self, idx): # A function to remove the idx-th key from this node, which is a leaf node for i in range(idx + 1, self.n): self.keys[i - 1] = self.keys[i] self.n -= 1 def remove_from_non_leaf(self, idx): # A function to remove the idx-th key from this node, which is a non-leaf node k = self.keys[idx] if self.C[idx].n >= self.t: pred = self.get_pred(idx) self.keys[idx] = pred self.C[idx].remove(pred) elif self.C[idx + 1].n >= self.t: succ = self.get_succ(idx) self.keys[idx] = succ self.C[idx + 1].remove(succ) else: self.merge(idx) self.C[idx].remove(k) def get_pred(self, idx): # A function to get the predecessor of the key at the idx-th position in the node cur = self.C[idx] while not cur.leaf: cur = cur.C[cur.n] return cur.keys[cur.n - 1] def get_succ(self, idx): # A function to get the successor of the key at the idx-th position in the node cur = self.C[idx + 1] while not cur.leaf: cur = cur.C[0] return cur.keys[0] def fill(self, idx): # A function to fill child C[idx] which has fewer than t-1 keys if idx != 0 and self.C[idx - 1].n >= self.t: self.borrow_from_prev(idx) elif idx != self.n and self.C[idx + 1].n >= self.t: self.borrow_from_next(idx) else: if idx != self.n: self.merge(idx) else: self.merge(idx - 1) def borrow_from_prev(self, idx): # A function to borrow a key from C[idx-1] and insert it into C[idx] child, sibling = self.C[idx], self.C[idx - 1] for i in range(child.n - 1, -1, -1): child.keys[i + 1] = child.keys[i] if not child.leaf: for i in range(child.n, -1, -1): child.C[i + 1] = child.C[i] child.keys[0] = self.keys[idx - 1] if not child.leaf: child.C[0] = sibling.C[sibling.n] self.keys[idx - 1] = sibling.keys[sibling.n - 1] child.n += 1 sibling.n -= 1 def borrow_from_next(self, idx): # A function to borrow a key from C[idx+1] and place it in C[idx] child, sibling = self.C[idx], self.C[idx + 1] child.keys[child.n] = self.keys[idx] if not child.leaf: child.C[child.n + 1] = sibling.C[0] self.keys[idx] = sibling.keys[0] for i in range(1, sibling.n): sibling.keys[i - 1] = sibling.keys[i] if not sibling.leaf: for i in range(1, sibling.n + 1): sibling.C[i - 1] = sibling.C[i] child.n += 1 sibling.n -= 1 def merge(self, idx): # A function to merge C[idx] with C[idx+1] child, sibling = self.C[idx], self.C[idx + 1] child.keys[self.t - 1] = self.keys[idx] for i in range(sibling.n): child.keys[i + self.t] = sibling.keys[i] if not child.leaf: for i in range(sibling.n + 1): child.C[i + self.t] = sibling.C[i] for i in range(idx + 1, self.n): self.keys[i - 1] = self.keys[i] for i in range(idx + 2, self.n + 1): self.C[i - 1] = self.C[i] child.n += sibling.n + 1 self.n -= 1 def insert_non_full(self, k): # A utility function to insert a new key in this node # The assumption is that the node must be non-full when this function is called i = self.n - 1 if self.leaf: while i >= 0 and self.keys[i] > k: self.keys[i + 1] = self.keys[i] i -= 1 self.keys[i + 1] = k self.n += 1 else: while i >= 0 and self.keys[i] > k: i -= 1 i += 1 if self.C[i].n == (2 * self.t - 1): self.split_child(i, self.C[i]) if self.keys[i] < k: i += 1 self.C[i].insert_non_full(k) def split_child(self, i, y): # A utility function to split the child y of this node # i is the index of y in the child array C[] z = BTreeNode(y.t, y.leaf) z.n = self.t - 1 for j in range(self.t - 1): z.keys[j] = y.keys[j + self.t] if not y.leaf: for j in range(self.t): z.C[j] = y.C[j + self.t] y.n = self.t - 1 for j in range(self.n, i, -1): self.C[j + 1] = self.C[j] self.C[i + 1] = z for j in range(self.n - 1, i - 1, -1): self.keys[j + 1] = self.keys[j] self.keys[i] = y.keys[self.t - 1] self.n += 1 def traverse(self): # A function to traverse all nodes in a subtree rooted with this node i = 0 while i < self.n: if not self.leaf: self.C[i].traverse() print(self.keys[i], end=" ") i += 1 if not self.leaf: self.C[i].traverse() class BTree: def __init__(self, t): # Constructor for BTree self.root = None # Pointer to the root node self.t = t # Minimum degree def traverse(self): # A function to traverse the B-tree if self.root: self.root.traverse() print() def search(self, k): # A function to search for a key in the B-tree return None if not self.root else self.root.search(k) def insert(self, k): # The main function that inserts a new key in the B-tree if not self.root: self.root = BTreeNode(self.t, True) self.root.keys[0] = k self.root.n = 1 else: if self.root.n == (2 * self.t - 1): s = BTreeNode(self.t, False) s.C[0] = self.root s.split_child(0, self.root) i = 0 if s.keys[0] < k: i += 1 s.C[i].insert_non_full(k) self.root = s else: self.root.insert_non_full(k) def remove(self, k): # The main function that removes a key from the B-tree if not self.root: print("The tree is empty") return self.root.remove(k) if self.root.n == 0: tmp = self.root if self.root.leaf: self.root = None else: self.root = self.root.C[0] del tmp # Driver program to test above functions if __name__ == "__main__": b_tree = BTree(3) keys_to_insert = [10, 5, 15, 2, 7, 12, 20] for key in keys_to_insert: b_tree.insert(key) print("Before Deletion:", end = " ") b_tree.traverse() b_tree.remove(5) print("After Deletion:", end = " ") b_tree.traverse() 
C#
// A BTree node class BTreeNode {  int[] keys; // An array of keys  int t; // Minimum degree (defines the range for number of keys)  BTreeNode[] C; // An array of child pointers  int n; // Current number of keys  bool leaf; // Is true when node is leaf. Otherwise false  public BTreeNode(int _t, bool _leaf) { // Constructor  t = _t;  leaf = _leaf;  keys = new int[2 * t - 1];  C = new BTreeNode[2 * t];  n = 0;  }  // A function to traverse all nodes in a subtree rooted with this node  public void Traverse() {  for (int i = 0; i < n; i++) {  if (!leaf) C[i].Traverse();  Console.Write(" " + keys[i]);  }  if (!leaf) C[n].Traverse();  }  // A function to search a key in subtree rooted with this node.  public BTreeNode Search(int k) { // returns NULL if k is not present.  int i = 0;  while (i < n && k > keys[i]) i++;  if (i < n && keys[i] == k) return this;  if (leaf) return null;  return C[i].Search(k);  }  // Other methods omitted for brevity... } class BTree {  BTreeNode root; // Pointer to root node  int t; // Minimum degree  public BTree(int _t) {  root = null;  t = _t;  }  public void Traverse() {  if (root != null) root.Traverse();  }  // Other methods omitted for brevity... } // Driver program to test above functions class Program {  static void Main() {  BTree t = new BTree(3); // A B-Tree with minimum degree 3  t.Insert(10);  t.Insert(5);  t.Insert(15);  t.Insert(2);  t.Insert(7);  t.Insert(12);  t.Insert(20);  Console.WriteLine("Before Deletion:");  t.Traverse();  Console.WriteLine();  t.Remove(5);  Console.WriteLine("After Deletion:");  t.Traverse();  Console.WriteLine();  } } 
JavaScript
// Define a Node class to represent a node in the binary tree class Node {  constructor(value) {  this.value = value;  this.left = null;  this.right = null;  }  traverse() {  if (this.left !== null) {  this.left.traverse();  }  process.stdout.write(this.value + " ");  if (this.right !== null) {  this.right.traverse();  }  } } // Define a BinaryTree class to represent the binary tree itself class BinaryTree {  constructor() {  this.root = null;  }  // Method to delete a node with the given value from the binary tree  deleteNode(value) {  // Call the deleteNodeFromTree method with the root node and the value to delete  this.root = this.deleteNodeFromTree(this.root, value);  }  // Recursive method to delete a node with the given value from the binary tree  deleteNodeFromTree(node, value) {  // If the node is null, return null  if (node === null) {  return null;  }  // If the value is less than the node's value, delete the node from the left subtree  if (value < node.value) {  node.left = this.deleteNodeFromTree(node.left, value);  }  // If the value is greater than the node's value, delete the node from the right subtree  else if (value > node.value) {  node.right = this.deleteNodeFromTree(node.right, value);  }  // If the value is equal to the node's value, delete the node  else {  // If the node has no children, set it to null  if (node.left === null && node.right === null) {  node = null;  }  // If the node has one child, replace it with its child  else if (node.left === null) {  node = node.right;  } else if (node.right === null) {  node = node.left;  }  // If the node has two children, replace it with the minimum value in its right subtree  else {  let minValue = this.findMinValue(node.right);  node.value = minValue;  node.right = this.deleteNodeFromTree(node.right, minValue);  }  }  // Return the modified node  return node;  }  // Method to find the minimum value in a subtree  findMinValue(node) {  // Keep traversing left until the leftmost leaf is reached  while (node.left !== null) {  node = node.left;  }  // Return the value of the leftmost leaf  return node.value;  } } // Example usage let binaryTree = new BinaryTree(); binaryTree.root = new Node(10); binaryTree.root.left = new Node(5); binaryTree.root.right = new Node(15); binaryTree.root.left.left = new Node(2); binaryTree.root.left.right = new Node(7); binaryTree.root.right.left = new Node(12); binaryTree.root.right.right = new Node(20); // Output the binary tree before deletion process.stdout.write("Before deletion: "); binaryTree.root.traverse(); // Delete the node with value 5 from the binary tree binaryTree.deleteNode(5); // Output the binary tree after deletion process.stdout.write("\nAfter deletion: "); binaryTree.root.traverse(); 

Output
Before Deletion: 2 5 7 10 12 15 20 After Deletion: 2 7 10 12 15 20 



Article Tags :

Explore