Saturday, September 21, 2024
Google search engine
HomeData Modelling & AIDeletion in Red-Black Tree

Deletion in Red-Black Tree

Deletion in a red-black tree is a bit more complicated than insertion. When a node is to be deleted, it can either have no children, one child or two children.

Here are the steps involved in deleting a node in a red-black tree:

  1. If the node to be deleted has no children, simply remove it and update the parent node.
  2. If the node to be deleted has only one child, replace the node with its child.
  3. If the node to be deleted has two children, then replace the node with its in-order successor, which is the leftmost node in the right subtree. Then delete the in-order successor node as if it has at most one child.
  4. After the node is deleted, the red-black properties might be violated. To restore these properties, some color changes and rotations are performed on the nodes in the tree. The changes are similar to those performed during insertion, but with different conditions.
  5. The deletion operation in a red-black tree takes O(log n) time on average, making it a good choice for searching and deleting elements in large data sets.

Reference books for more information on Red-Black Trees and their implementation in various programming languages:

  1. “Introduction to Algorithms” by Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein
  2. “The Art of Computer Programming, Volume 3: Sorting and Searching” by Donald E. Knuth
  3. “Algorithms in C, Part 5: Graph Algorithms” by Robert Sedgewick.

We have discussed the following topics on the Red-Black tree in previous posts. We strongly recommend referring following post as a prerequisite of this post.
Red-Black Tree Introduction 
Red Black Tree Insert

Insertion Vs Deletion: 
Like Insertion, recoloring and rotations are used to maintain the Red-Black properties.
In the insert operation, we check the color of the uncle to decide the appropriate case. In the delete operation, we check the color of the sibling to decide the appropriate case.
The main property that violates after insertion is two consecutive reds. In delete, the main violated property is, change of black height in subtrees as deletion of a black node may cause reduced black height in one root to leaf path.
Deletion is a fairly complex process.  To understand deletion, the notion of double black is used.  When a black node is deleted and replaced by a black child, the child is marked as double black. The main task now becomes to convert this double black to single black.
Deletion Steps 
Following are detailed steps for deletion.
1) Perform standard BST delete. When we perform standard delete operation in BST, we always end up deleting a node which is an either leaf or has only one child (For an internal node, we copy the successor and then recursively call delete for successor, successor is always a leaf node or a node with one child). So we only need to handle cases where a node is leaf or has one child. Let v be the node to be deleted and u be the child that replaces v (Note that u is NULL when v is a leaf and color of NULL is considered as Black).
2) Simple Case: If either u or v is red, we mark the replaced child as black (No change in black height). Note that both u and v cannot be red as v is parent of u and two consecutive reds are not allowed in red-black tree. 
 

rbdelete11

3) If Both u and v are Black.
3.1) Color u as double black.  Now our task reduces to convert this double black to single black. Note that If v is leaf, then u is NULL and color of NULL is considered black. So the deletion of a black leaf also causes a double black.
 

rbdelete12_new

3.2) Do following while the current node u is double black, and it is not the root. Let sibling of node be s
….(a): If sibling s is black and at least one of sibling’s children is red, perform rotation(s). Let the red child of s be r. This case can be divided in four subcases depending upon positions of s and r.
…………..(i) Left Left Case (s is left child of its parent and r is left child of s or both children of s are red). This is mirror of right right case shown in below diagram.
…………..(ii) Left Right Case (s is left child of its parent and r is right child). This is mirror of right left case shown in below diagram.
…………..(iii) Right Right Case (s is right child of its parent and r is right child of s or both children of s are red) 
 

rbdelete13New

…………..(iv) Right Left Case (s is right child of its parent and r is left child of s) 
 

rbdelete14

…..(b): If sibling is black and its both children are black, perform recoloring, and recur for the parent if parent is black. 
 

rbdelete15

In this case, if parent was red, then we didn’t need to recur for parent, we can simply make it black (red + double black = single black)
…..(c): If sibling is red, perform a rotation to move old sibling up, recolor the old sibling and parent. The new sibling is always black (See the below diagram). This mainly converts the tree to black sibling case (by rotation) and leads to case (a) or (b). This case can be divided in two subcases. 
…………..(i) Left Case (s is left child of its parent). This is mirror of right right case shown in below diagram. We right rotate the parent p. 
…………..(ii) Right Case (s is right child of its parent). We left rotate the parent p. 
 

rbdelete16

3.3) If u is root, make it single black and return (Black height of complete tree reduces by 1).
below is the C++ implementation of above approach: 
 

CPP




#include <iostream>
#include <queue>
using namespace std;
 
enum COLOR { RED, BLACK };
 
class Node {
public:
  int val;
  COLOR color;
  Node *left, *right, *parent;
 
  Node(int val) : val(val) {
    parent = left = right = NULL;
 
    // Node is created during insertion
    // Node is red at insertion
    color = RED;
  }
 
  // returns pointer to uncle
  Node *uncle() {
    // If no parent or grandparent, then no uncle
    if (parent == NULL or parent->parent == NULL)
      return NULL;
 
    if (parent->isOnLeft())
      // uncle on right
      return parent->parent->right;
    else
      // uncle on left
      return parent->parent->left;
  }
 
  // check if node is left child of parent
  bool isOnLeft() { return this == parent->left; }
 
  // returns pointer to sibling
  Node *sibling() {
    // sibling null if no parent
    if (parent == NULL)
      return NULL;
 
    if (isOnLeft())
      return parent->right;
 
    return parent->left;
  }
 
  // moves node down and moves given node in its place
  void moveDown(Node *nParent) {
    if (parent != NULL) {
      if (isOnLeft()) {
        parent->left = nParent;
      } else {
        parent->right = nParent;
      }
    }
    nParent->parent = parent;
    parent = nParent;
  }
 
  bool hasRedChild() {
    return (left != NULL and left->color == RED) or
           (right != NULL and right->color == RED);
  }
};
 
class RBTree {
  Node *root;
 
  // left rotates the given node
  void leftRotate(Node *x) {
    // new parent will be node's right child
    Node *nParent = x->right;
 
    // update root if current node is root
    if (x == root)
      root = nParent;
 
    x->moveDown(nParent);
 
    // connect x with new parent's left element
    x->right = nParent->left;
    // connect new parent's left element with node
    // if it is not null
    if (nParent->left != NULL)
      nParent->left->parent = x;
 
    // connect new parent with x
    nParent->left = x;
  }
 
  void rightRotate(Node *x) {
    // new parent will be node's left child
    Node *nParent = x->left;
 
    // update root if current node is root
    if (x == root)
      root = nParent;
 
    x->moveDown(nParent);
 
    // connect x with new parent's right element
    x->left = nParent->right;
    // connect new parent's right element with node
    // if it is not null
    if (nParent->right != NULL)
      nParent->right->parent = x;
 
    // connect new parent with x
    nParent->right = x;
  }
 
  void swapColors(Node *x1, Node *x2) {
    COLOR temp;
    temp = x1->color;
    x1->color = x2->color;
    x2->color = temp;
  }
 
  void swapValues(Node *u, Node *v) {
    int temp;
    temp = u->val;
    u->val = v->val;
    v->val = temp;
  }
 
  // fix red red at given node
  void fixRedRed(Node *x) {
    // if x is root color it black and return
    if (x == root) {
      x->color = BLACK;
      return;
    }
 
    // initialize parent, grandparent, uncle
    Node *parent = x->parent, *grandparent = parent->parent,
         *uncle = x->uncle();
 
    if (parent->color != BLACK) {
      if (uncle != NULL && uncle->color == RED) {
        // uncle red, perform recoloring and recurse
        parent->color = BLACK;
        uncle->color = BLACK;
        grandparent->color = RED;
        fixRedRed(grandparent);
      } else {
        // Else perform LR, LL, RL, RR
        if (parent->isOnLeft()) {
          if (x->isOnLeft()) {
            // for left right
            swapColors(parent, grandparent);
          } else {
            leftRotate(parent);
            swapColors(x, grandparent);
          }
          // for left left and left right
          rightRotate(grandparent);
        } else {
          if (x->isOnLeft()) {
            // for right left
            rightRotate(parent);
            swapColors(x, grandparent);
          } else {
            swapColors(parent, grandparent);
          }
 
          // for right right and right left
          leftRotate(grandparent);
        }
      }
    }
  }
 
  // find node that do not have a left child
  // in the subtree of the given node
  Node *successor(Node *x) {
    Node *temp = x;
 
    while (temp->left != NULL)
      temp = temp->left;
 
    return temp;
  }
 
  // find node that replaces a deleted node in BST
  Node *BSTreplace(Node *x) {
    // when node have 2 children
    if (x->left != NULL and x->right != NULL)
      return successor(x->right);
 
    // when leaf
    if (x->left == NULL and x->right == NULL)
      return NULL;
 
    // when single child
    if (x->left != NULL)
      return x->left;
    else
      return x->right;
  }
 
  // deletes the given node
  void deleteNode(Node *v) {
    Node *u = BSTreplace(v);
 
    // True when u and v are both black
    bool uvBlack = ((u == NULL or u->color == BLACK) and (v->color == BLACK));
    Node *parent = v->parent;
 
    if (u == NULL) {
      // u is NULL therefore v is leaf
      if (v == root) {
        // v is root, making root null
        root = NULL;
      } else {
        if (uvBlack) {
          // u and v both black
          // v is leaf, fix double black at v
          fixDoubleBlack(v);
        } else {
          // u or v is red
          if (v->sibling() != NULL)
            // sibling is not null, make it red"
            v->sibling()->color = RED;
        }
 
        // delete v from the tree
        if (v->isOnLeft()) {
          parent->left = NULL;
        } else {
          parent->right = NULL;
        }
      }
      delete v;
      return;
    }
 
    if (v->left == NULL or v->right == NULL) {
      // v has 1 child
      if (v == root) {
        // v is root, assign the value of u to v, and delete u
        v->val = u->val;
        v->left = v->right = NULL;
        delete u;
      } else {
        // Detach v from tree and move u up
        if (v->isOnLeft()) {
          parent->left = u;
        } else {
          parent->right = u;
        }
        delete v;
        u->parent = parent;
        if (uvBlack) {
          // u and v both black, fix double black at u
          fixDoubleBlack(u);
        } else {
          // u or v red, color u black
          u->color = BLACK;
        }
      }
      return;
    }
 
    // v has 2 children, swap values with successor and recurse
    swapValues(u, v);
    deleteNode(u);
  }
 
  void fixDoubleBlack(Node *x) {
    if (x == root)
      // Reached root
      return;
 
    Node *sibling = x->sibling(), *parent = x->parent;
    if (sibling == NULL) {
      // No sibling, double black pushed up
      fixDoubleBlack(parent);
    } else {
      if (sibling->color == RED) {
        // Sibling red
        parent->color = RED;
        sibling->color = BLACK;
        if (sibling->isOnLeft()) {
          // left case
          rightRotate(parent);
        } else {
          // right case
          leftRotate(parent);
        }
        fixDoubleBlack(x);
      } else {
        // Sibling black
        if (sibling->hasRedChild()) {
          // at least 1 red children
          if (sibling->left != NULL and sibling->left->color == RED) {
            if (sibling->isOnLeft()) {
              // left left
              sibling->left->color = sibling->color;
              sibling->color = parent->color;
              rightRotate(parent);
            } else {
              // right left
              sibling->left->color = parent->color;
              rightRotate(sibling);
              leftRotate(parent);
            }
          } else {
            if (sibling->isOnLeft()) {
              // left right
              sibling->right->color = parent->color;
              leftRotate(sibling);
              rightRotate(parent);
            } else {
              // right right
              sibling->right->color = sibling->color;
              sibling->color = parent->color;
              leftRotate(parent);
            }
          }
          parent->color = BLACK;
        } else {
          // 2 black children
          sibling->color = RED;
          if (parent->color == BLACK)
            fixDoubleBlack(parent);
          else
            parent->color = BLACK;
        }
      }
    }
  }
 
  // prints level order for given node
  void levelOrder(Node *x) {
    if (x == NULL)
      // return if node is null
      return;
 
    // queue for level order
    queue<Node *> q;
    Node *curr;
 
    // push x
    q.push(x);
 
    while (!q.empty()) {
      // while q is not empty
      // dequeue
      curr = q.front();
      q.pop();
 
      // print node value
      cout << curr->val << " ";
 
      // push children to queue
      if (curr->left != NULL)
        q.push(curr->left);
      if (curr->right != NULL)
        q.push(curr->right);
    }
  }
 
  // prints inorder recursively
  void inorder(Node *x) {
    if (x == NULL)
      return;
    inorder(x->left);
    cout << x->val << " ";
    inorder(x->right);
  }
 
public:
  // constructor
  // initialize root
  RBTree() { root = NULL; }
 
  Node *getRoot() { return root; }
 
  // searches for given value
  // if found returns the node (used for delete)
  // else returns the last node while traversing (used in insert)
  Node *search(int n) {
    Node *temp = root;
    while (temp != NULL) {
      if (n < temp->val) {
        if (temp->left == NULL)
          break;
        else
          temp = temp->left;
      } else if (n == temp->val) {
        break;
      } else {
        if (temp->right == NULL)
          break;
        else
          temp = temp->right;
      }
    }
 
    return temp;
  }
 
  // inserts the given value to tree
  void insert(int n) {
    Node *newNode = new Node(n);
    if (root == NULL) {
      // when root is null
      // simply insert value at root
      newNode->color = BLACK;
      root = newNode;
    } else {
      Node *temp = search(n);
 
      if (temp->val == n) {
        // return if value already exists
        return;
      }
 
      // if value is not found, search returns the node
      // where the value is to be inserted
 
      // connect new node to correct node
      newNode->parent = temp;
 
      if (n < temp->val)
        temp->left = newNode;
      else
        temp->right = newNode;
 
      // fix red red violation if exists
      fixRedRed(newNode);
    }
  }
 
  // utility function that deletes the node with given value
  void deleteByVal(int n) {
    if (root == NULL)
      // Tree is empty
      return;
 
    Node *v = search(n), *u;
 
    if (v->val != n) {
      cout << "No node found to delete with value:" << n << endl;
      return;
    }
 
    deleteNode(v);
  }
 
  // prints inorder of the tree
  void printInOrder() {
    cout << "Inorder: " << endl;
    if (root == NULL)
      cout << "Tree is empty" << endl;
    else
      inorder(root);
    cout << endl;
  }
 
  // prints level order of the tree
  void printLevelOrder() {
    cout << "Level order: " << endl;
    if (root == NULL)
      cout << "Tree is empty" << endl;
    else
      levelOrder(root);
    cout << endl;
  }
};
 
int main() {
  RBTree tree;
 
  tree.insert(7);
  tree.insert(3);
  tree.insert(18);
  tree.insert(10);
  tree.insert(22);
  tree.insert(8);
  tree.insert(11);
  tree.insert(26);
  tree.insert(2);
  tree.insert(6);
  tree.insert(13);
 
  tree.printInOrder();
  tree.printLevelOrder();
 
  cout<<endl<<"Deleting 18, 11, 3, 10, 22"<<endl;
 
  tree.deleteByVal(18);
  tree.deleteByVal(11);
  tree.deleteByVal(3);
  tree.deleteByVal(10);
  tree.deleteByVal(22);
 
  tree.printInOrder();
  tree.printLevelOrder();
  return 0;
}


Java




// Java Code for the above approach
 
import java.util.LinkedList;
import java.util.Queue;
 
enum COLOR { RED, BLACK }
 
class Node {
    int val;
    COLOR color;
    Node left, right, parent;
 
    Node(int val) {
        this.val = val;
        parent = left = right = null;
         
        // Node is created during insertion
        // Node is red at insertion
        color = COLOR.RED;
    }
     
    // returns pointer to uncle
    Node uncle() {
         
        // If no parent or grandparent, then no uncle
        if (parent == null || parent.parent == null)
            return null;
         
        if (parent.isOnLeft())
            // uncle on right
            return parent.parent.right;
        else
        // uncle on left
            return parent.parent.left;
    }
     
      // check if node is left child of parent
    boolean isOnLeft() {
        return this == parent.left;
    }
     
    // returns pointer to sibling
    Node sibling() {
         
        // sibling null if no parent
        if (parent == null)
            return null;
 
        if (isOnLeft())
            return parent.right;
 
        return parent.left;
    }
     
    // moves node down and moves given node in its place
    void moveDown(Node nParent) {
        if (parent != null) {
            if (isOnLeft())
                parent.left = nParent;
            else
                parent.right = nParent;
        }
        nParent.parent = parent;
        parent = nParent;
    }
 
    boolean hasRedChild() {
        return (left != null && left.color == COLOR.RED) ||
                (right != null && right.color == COLOR.RED);
    }
}
 
class RBTree {
    Node root;
     
    // left rotates the given node
    void leftRotate(Node x) {
        // new parent will be node's right child
        Node nParent = x.right;
         
        // update root if current node is root
        if (x == root)
            root = nParent;
             
        x.moveDown(nParent);
         
        // connect x with new parent's left element
        x.right = nParent.left;
         
        // connect new parent's left element with node
        // if it is not null
        if (nParent.left != null)
            nParent.left.parent = x;
         
        // connect new parent with x
        nParent.left = x;
    }
 
    void rightRotate(Node x) {
         
        // new parent will be node's left child
        Node nParent = x.left;
         
        // update root if current node is root
        if (x == root)
            root = nParent;
 
        x.moveDown(nParent);
         
        // connect x with new parent's right element
        x.left = nParent.right;
         
        // connect new parent's right element with node
        // if it is not null
        if (nParent.right != null)
            nParent.right.parent = x;
         
        // connect new parent with x
        nParent.right = x;
    }
 
    void swapColors(Node x1, Node x2) {
        COLOR temp = x1.color;
        x1.color = x2.color;
        x2.color = temp;
    }
 
    void swapValues(Node u, Node v) {
        int temp = u.val;
        u.val = v.val;
        v.val = temp;
    }
     
    // fix red red at given node
    void fixRedRed(Node x) {
         
         // if x is root color it black and return
        if (x == root) {
            x.color = COLOR.BLACK;
            return;
        }
         
        // initialize parent, grandparent, uncle
        Node parent = x.parent, grandparent = parent.parent, uncle = x.uncle();
 
        if (parent.color != COLOR.BLACK) {
            if (uncle != null && uncle.color == COLOR.RED) {
                 
                // uncle red, perform recoloring and recurse
                parent.color = COLOR.BLACK;
                uncle.color = COLOR.BLACK;
                grandparent.color = COLOR.RED;
                fixRedRed(grandparent);
            } else {
                // Else perform LR, LL, RL, RR
                if (parent.isOnLeft()) {
                    if (x.isOnLeft())
                        // for left right
                        swapColors(parent, grandparent);
                    else {
                        leftRotate(parent);
                        swapColors(x, grandparent);
                    }
                    // for left left and left right
                    rightRotate(grandparent);
                } else {
                    if (x.isOnLeft()) {
                        // for right left
                        rightRotate(parent);
                        swapColors(x, grandparent);
                    } else
                        swapColors(parent, grandparent);
                         
                    // for right right and right left
                    leftRotate(grandparent);
                }
            }
        }
    }
    // find node that do not have a left child
    // in the subtree of the given node
    Node successor(Node x) {
        Node temp = x;
        while (temp.left != null)
            temp = temp.left;
        return temp;
    }
     
    // find node that replaces a deleted node in BST
    Node BSTreplace(Node x) {
        // when node have 2 children
        if (x.left != null && x.right != null)
            return successor(x.right);
             
        // when leaf
        if (x.left == null && x.right == null)
            return null;
             
        // when single child
        if (x.left != null)
            return x.left;
        else
            return x.right;
    }
     
    // deletes the given node
    void deleteNode(Node v) {
        Node u = BSTreplace(v);
        // True when u and v are both black
        boolean uvBlack = ((u == null || u.color == COLOR.BLACK) && (v.color == COLOR.BLACK));
        Node parent = v.parent;
 
        if (u == null) {
            // u is NULL therefore v is leaf
            if (v == root)
             // v is root, making root null
                root = null;
            else {
                if (uvBlack)
                // u and v both black
                // v is leaf, fix double black at v
                    fixDoubleBlack(v);
                     
                // u or v is red
                else if (v.sibling() != null)
                // sibling is not null, make it red
                    v.sibling().color = COLOR.RED;
                 
                // delete v from the tree
                if (v.isOnLeft())
                    parent.left = null;
                else
                    parent.right = null;
            }
            return;
        }
 
        if (v.left == null || v.right == null) {
            // v has 1 child
            if (v == root) {
                // v is root, assign the value of u to v, and delete u
                v.val = u.val;
                v.left = v.right = null;
                // delete u;
            } else {
                // Detach v from tree and move u up
                if (v.isOnLeft())
                    parent.left = u;
                else
                    parent.right = u;
 
                u.parent = parent;
 
                if (uvBlack)
                // u and v both black, fix double black at u
                    fixDoubleBlack(u);
                else
                // u or v red, color u black
                    u.color = COLOR.BLACK;
            }
            return;
        }
         
        // v has 2 children, swap values with successor and recurse
        swapValues(u, v);
        deleteNode(u);
    }
 
    void fixDoubleBlack(Node x) {
        // Reached root
        if (x == root)
            return;
 
        Node sibling = x.sibling(), parent = x.parent;
 
        if (sibling == null)
        // No sibling, double black pushed up
            fixDoubleBlack(parent);
        else {
            if (sibling.color == COLOR.RED) {
                // sibling red
                parent.color = COLOR.RED;
                sibling.color = COLOR.BLACK;
 
                if (sibling.isOnLeft())
                    // right case
                    rightRotate(parent);
                else
                    // right case
                    leftRotate(parent);
 
                fixDoubleBlack(x);
            } else {
                // Sibling black
                if (sibling.hasRedChild()) {
                    // at least 1 red children
                    if (sibling.left != null && sibling.left.color == COLOR.RED) {
                        if (sibling.isOnLeft()) {
                            // left left
                            sibling.left.color = sibling.color;
                            sibling.color = parent.color;
                            rightRotate(parent);
                        } else {
                            // right right
                            sibling.left.color = parent.color;
                            rightRotate(sibling);
                            leftRotate(parent);
                        }
                    } else {
                        if (sibling.isOnLeft()) {
                            // left right
                            sibling.right.color = parent.color;
                            leftRotate(sibling);
                            rightRotate(parent);
                        } else {
                            // right right
                            sibling.right.color = sibling.color;
                            sibling.color = parent.color;
                            leftRotate(parent);
                        }
                    }
                    parent.color = COLOR.BLACK;
                } else {
                    // 2 black children
                    sibling.color = COLOR.RED;
                    if (parent.color == COLOR.BLACK)
                        fixDoubleBlack(parent);
                    else
                        parent.color = COLOR.BLACK;
                }
            }
        }
    }
     
    // prints level order for given node
    void levelOrder(Node x) {
        if (x == null)
            return;
         
        // queue for level order
        Queue<Node> q = new LinkedList<>();
        Node curr;
 
        q.add(x);
 
        while (!q.isEmpty()) {
            curr = q.poll();
            // print node value
            System.out.print(curr.val + " ");
             
            // push children to queue
            if (curr.left != null)
                q.add(curr.left);
            if (curr.right != null)
                q.add(curr.right);
        }
    }
     
    // prints inorder recursively
    void inorder(Node x) {
        if (x == null)
            return;
 
        inorder(x.left);
        System.out.print(x.val + " ");
        inorder(x.right);
    }
     
    // constructor
    // initialize root
    RBTree() {
        root = null;
    }
 
    Node getRoot() {
        return root;
    }
     
    // searches for given value
    // if found returns the node (used for delete)
    // else returns the last node while traversing (used in insert)
    Node search(int n) {
        Node temp = root;
        while (temp != null) {
            if (n < temp.val) {
                if (temp.left == null)
                    break;
                else
                    temp = temp.left;
            } else if (n == temp.val) {
                break;
            } else {
                if (temp.right == null)
                    break;
                else
                    temp = temp.right;
            }
        }
 
        return temp;
    }
     
    // inserts the given value to tree
    void insert(int n) {
        Node newNode = new Node(n);
        if (root == null) {
            // when root is null
            // simply insert value at root
            newNode.color = COLOR.BLACK;
            root = newNode;
        } else {
            Node temp = search(n);
             
            // return if value already exists
            if (temp.val == n)
                return;
                 
            // if value is not found, search returns the node
            // where the value is to be inserted
  
            // connect new node to correct node
            newNode.parent = temp;
 
            if (n < temp.val)
                temp.left = newNode;
            else
                temp.right = newNode;
             
            // fix red red violation if exists
            fixRedRed(newNode);
        }
    }
     
    // utility function that deletes the node with given value
    void deleteByVal(int n) {
        if (root == null)
            return;
 
        Node v = search(n), u;
 
        if (v.val != n) {
            System.out.println("No node found to delete with value: " + n);
            return;
        }
 
        deleteNode(v);
    }
     
    // prints inorder of the tree
    void printInOrder() {
        System.out.println("Inorder: ");
        if (root == null)
            System.out.println("Tree is empty");
        else
            inorder(root);
        System.out.println();
    }
     
    // prints level order of the tree
    void printLevelOrder() {
        System.out.println("Level order: ");
        if (root == null)
            System.out.println("Tree is empty");
        else
            levelOrder(root);
        System.out.println();
    }
}
 
public class Main {
    public static void main(String[] args) {
        RBTree tree = new RBTree();
 
        tree.insert(7);
        tree.insert(3);
        tree.insert(18);
        tree.insert(10);
        tree.insert(22);
        tree.insert(8);
        tree.insert(11);
        tree.insert(26);
        tree.insert(2);
        tree.insert(6);
        tree.insert(13);
 
        tree.printInOrder();
        tree.printLevelOrder();
 
        System.out.println("\nDeleting 18, 11, 3, 10, 22\n");
 
        tree.deleteByVal(18);
        tree.deleteByVal(11);
        tree.deleteByVal(3);
        tree.deleteByVal(10);
        tree.deleteByVal(22);
 
        tree.printInOrder();
        tree.printLevelOrder();
    }
}
 
// This code is contributed by Abhinav Mahajan (abhinav_m22).


Output: 

Inorder: 
2 3 6 7 8 10 11 13 18 22 26
Level order:
10 7 18 3 8 11 22 2 6 13 26
Deleting 18, 11, 3, 10, 22
Inorder:
2 6 7 8 13 26
Level order:
13 7 26 6 8 2

References: 

https://www.cs.purdue.edu/homes/ayg/CS251/slides/chap13c.pdf 
Introduction to Algorithms 3rd Edition by Clifford Stein, Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above
 

Feeling lost in the world of random DSA topics, wasting time without progress? It’s time for a change! Join our DSA course, where we’ll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!

Previous article
Next article
RELATED ARTICLES

Most Popular

Recent Comments