# Deletion in a Red-Black Tree

In this tutorial, you will learn how a node is deleted from a red-black tree is. Also, you will find working examples of deletions performed on a red-black tree in C, C++, Java and Python.

Red-Black tree is a self-balancing binary search tree in which each node contains an extra bit for denoting the color of the node, either red or black.

Deleting a node may or may not disrupt the red-black properties of a red-black tree. If this action violates the red-black properties, then a fixing algorithm is used to regain the red-black properties.

## Deleting an element from a Red-Black Tree

This operation removes a node from the tree. After deleting a node, the red-black property is maintained again.

1. Let the nodeToBeDeleted be:
2. Save the color of nodeToBeDeleted in origrinalColor.
3. If the left child of nodeToBeDeleted is NULL
1. Assign the right child of nodeToBeDeleted to x.
2. Transplant nodeToBeDeleted with x.
4. Else if the right child of nodeToBeDeleted is NULL
1. Assign the left child of nodeToBeDeleted into x.
2. Transplant nodeToBeDeleted with x.
5. Else
1. Assign the minimum of right subtree of noteToBeDeleted into y.
2. Save the color of y in originalColor.
3. Assign the rightChild of y into x.
4. If y is a child of nodeToBeDeleted, then set the parent of x as y.
5. Else, transplant y with rightChild of y.
6. Transplant nodeToBeDeleted with y.
7. Set the color of y with originalColor.
6. If the originalColor is BLACK, call DeleteFix(x).

## Algorithm to maintain Red-Black property after deletion

This algorithm is implemented when a black node is deleted because it violates the black depth property of the red-black tree.

This violation is corrected by assuming that node x (which is occupying y's original position) has an extra black. This makes node x neither red nor black. It is either doubly black or black-and-red. This violates the red-black properties.

However, the color attribute of x is not changed rather the extra black is represented in x's pointing to the node.

The extra black can be removed if

1. It reaches the root node.
2. If x points to a red-black node. In this case, x is colored black.
3. Suitable rotations and recolorings are performed.

Following algorithm retains the properties of a red-black tree.

1. Do the following until the x is not the root of the tree and the color of x is BLACK
2. If x is the left child of its parent then,
1. Assign w to the sibling of x.
2. If the sibling of x is RED,
Case-I:
1. Set the color of the right child of the parent of x as BLACK.
2. Set the color of the parent of x as RED.
3. Left-Rotate the parent of x.
4. Assign the rightChild of the parent of x to w.
3. If the color of both the right and the leftChild of w is BLACK,
Case-II:
1. Set the color of w as RED
2. Assign the parent of x to x.
4. Else if the color of the rightChild of w is BLACK
Case-III:
1. Set the color of the leftChild of w as BLACK
2. Set the color of w as RED
3. Right-Rotate w.
4. Assign the rightChild of the parent of x to w.
5. If any of the above cases do not occur, then do the following.
Case-IV:
1. Set the color of w as the color of the parent of x.
2. Set the color of the parent of parent of x as BLACK.
3. Set the color of the right child of w as BLACK.
4. Left-Rotate the parent of x.
5. Set x as the root of the tree.
3. Else same as above with right changed to left and vice versa.
4. Set the color of x as BLACK.

The workflow of the above cases can be understood with the help of the flowchart below.

## Python, Java and C/C++ Examples

# Implementing Red-Black Tree in Python

import sys

class Node():
def __init__(self, data):
self.data = data
self.parent = None
self.left = None
self.right = None
self.color = 1

class RedBlackTree():
def __init__(self):
self.TNULL = Node(0)
self.TNULL.color = 0
self.TNULL.left = None
self.TNULL.right = None
self.root = self.TNULL

def __pre_order_helper(self, node):
if node != TNULL:
sys.stdout.write(node.data + " ")
self.__pre_order_helper(node.left)
self.__pre_order_helper(node.right)

def __in_order_helper(self, node):
if node != TNULL:
self.__in_order_helper(node.left)
sys.stdout.write(node.data + " ")
self.__in_order_helper(node.right)

def __post_order_helper(self, node):
if node != TNULL:
self.__post_order_helper(node.left)
self.__post_order_helper(node.right)
sys.stdout.write(node.data + " ")

def __search_tree_helper(self, node, key):
if node == TNULL or key == node.data:
return node

if key < node.data:
return self.__search_tree_helper(node.left, key)
return self.__search_tree_helper(node.right, key)

def delete_fix(self, x):
while x != self.root and x.color == 0:
if x == x.parent.left:
s = x.parent.right
if s.color == 1:
s.color = 0
x.parent.color = 1
self.left_rotate(x.parent)
s = x.parent.right

if s.left.color == 0 and s.right.color == 0:
s.color = 1
x = x.parent
else:
if s.right.color == 0:
s.left.color = 0
s.color = 1
self.right_rotate(s)
s = x.parent.right

s.color = x.parent.color
x.parent.color = 0
s.right.color = 0
self.left_rotate(x.parent)
x = self.root
else:
s = x.parent.left
if s.color == 1:
s.color = 0
x.parent.color = 1
self.right_rotate(x.parent)
s = x.parent.left

if s.right.color == 0 and s.right.color == 0:
s.color = 1
x = x.parent
else:
if s.left.color == 0:
s.right.color = 0
s.color = 1
self.left_rotate(s)
s = x.parent.left

s.color = x.parent.color
x.parent.color = 0
s.left.color = 0
self.right_rotate(x.parent)
x = self.root
x.color = 0

def __rb_transplant(self, u, v):
if u.parent == None:
self.root = v
elif u == u.parent.left:
u.parent.left = v
else:
u.parent.right = v
v.parent = u.parent

def __delete_node_helper(self, node, key):
z = self.TNULL
while node != self.TNULL:
if node.data == key:
z = node

if node.data <= key:
node = node.right
else:
node = node.left

if z == self.TNULL:
print "Couldn't find key in the tree"
return

y = z
y_original_color = y.color
if z.left == self.TNULL:
x = z.right
self.__rb_transplant(z, z.right)
elif (z.right == self.TNULL):
x = z.left
self.__rb_transplant(z, z.left)
else:
y = self.minimum(z.right)
y_original_color = y.color
x = y.right
if y.parent == z:
x.parent = y
else:
self.__rb_transplant(y, y.right)
y.right = z.right
y.right.parent = y

self.__rb_transplant(z, y)
y.left = z.left
y.left.parent = y
y.color = z.color
if y_original_color == 0:
self.delete_fix(x)

def  __fix_insert(self, k):
while k.parent.color == 1:
if k.parent == k.parent.parent.right:
u = k.parent.parent.left
if u.color == 1:
u.color = 0
k.parent.color = 0
k.parent.parent.color = 1
k = k.parent.parent
else:
if k == k.parent.left:
k = k.parent
self.right_rotate(k)
k.parent.color = 0
k.parent.parent.color = 1
self.left_rotate(k.parent.parent)
else:
u = k.parent.parent.right

if u.color == 1:
u.color = 0
k.parent.color = 0
k.parent.parent.color = 1
k = k.parent.parent
else:
if k == k.parent.right:
k = k.parent
self.left_rotate(k)
k.parent.color = 0
k.parent.parent.color = 1
self.right_rotate(k.parent.parent)
if k == self.root:
break
self.root.color = 0

def __print_helper(self, node, indent, last):
if node != self.TNULL:
sys.stdout.write(indent)
if last:
sys.stdout.write("R----")
indent += "     "
else:
sys.stdout.write("L----")
indent += "|    "

s_color = "RED" if node.color == 1 else "BLACK"
print str(node.data) + "(" + s_color + ")"
self.__print_helper(node.left, indent, False)
self.__print_helper(node.right, indent, True)

def preorder(self):
self.__pre_order_helper(self.root)

def inorder(self):
self.__in_order_helper(self.root)

def postorder(self):
self.__post_order_helper(self.root)

def searchTree(self, k):
return self.__search_tree_helper(self.root, k)

def minimum(self, node):
while node.left != self.TNULL:
node = node.left
return node

def maximum(self, node):
while node.right != self.TNULL:
node = node.right
return node

def successor(self, x):
if x.right != self.TNULL:
return self.minimum(x.right)

y = x.parent
while y != self.TNULL and x == y.right:
x = y
y = y.parent
return y

def predecessor(self,  x):
if (x.left != self.TNULL):
return self.maximum(x.left)

y = x.parent
while y != self.TNULL and x == y.left:
x = y
y = y.parent

return y

def left_rotate(self, x):
y = x.right
x.right = y.left
if y.left != self.TNULL:
y.left.parent = x

y.parent = x.parent
if x.parent == None:
self.root = y
elif x == x.parent.left:
x.parent.left = y
else:
x.parent.right = y
y.left = x
x.parent = y

def right_rotate(self, x):
y = x.left
x.left = y.right
if y.right != self.TNULL:
y.right.parent = x

y.parent = x.parent
if x.parent == None:
self.root = y
elif x == x.parent.right:
x.parent.right = y
else:
x.parent.left = y
y.right = x
x.parent = y

def insert(self, key):
node = Node(key)
node.parent = None
node.data = key
node.left = self.TNULL
node.right = self.TNULL
node.color = 1

y = None
x = self.root

while x != self.TNULL:
y = x
if node.data < x.data:
x = x.left
else:
x = x.right

node.parent = y
if y == None:
self.root = node
elif node.data < y.data:
y.left = node
else:
y.right = node

if node.parent == None:
node.color = 0
return

if node.parent.parent == None:
return

self.__fix_insert(node)

def get_root(self):
return self.root

def delete_node(self, data):
self.__delete_node_helper(self.root, data)

def print_tree(self):
self.__print_helper(self.root, "", True)

if __name__ == "__main__":
bst = RedBlackTree()

bst.insert(55);
bst.insert(40);
bst.insert(65);
bst.insert(60);
bst.insert(75);
bst.insert(57);

bst.print_tree()

print("\nAfter deleting an element")
bst.delete_node(40)
bst.print_tree()
// Implementing Red-Black Tree in Java

class Node {
int data;
Node parent;
Node left;
Node right;
int color;
}

public class RedBlackTree {
private Node root;
private Node TNULL;

private void preOrderHelper(Node node) {
if (node != TNULL) {
System.out.print(node.data + " ");
preOrderHelper(node.left);
preOrderHelper(node.right);
}
}

private void inOrderHelper(Node node) {
if (node != TNULL) {
inOrderHelper(node.left);
System.out.print(node.data + " ");
inOrderHelper(node.right);
}
}

private void postOrderHelper(Node node) {
if (node != TNULL) {
postOrderHelper(node.left);
postOrderHelper(node.right);
System.out.print(node.data + " ");
}
}

private Node searchTreeHelper(Node node, int key) {
if (node == TNULL || key == node.data) {
return node;
}

if (key < node.data) {
return searchTreeHelper(node.left, key);
}
return searchTreeHelper(node.right, key);
}

private void fixDelete(Node x) {
Node s;
while (x != root && x.color == 0) {
if (x == x.parent.left) {
s = x.parent.right;
if (s.color == 1) {
s.color = 0;
x.parent.color = 1;
leftRotate(x.parent);
s = x.parent.right;
}

if (s.left.color == 0 && s.right.color == 0) {
s.color = 1;
x = x.parent;
} else {
if (s.right.color == 0) {
s.left.color = 0;
s.color = 1;
rightRotate(s);
s = x.parent.right;
}

s.color = x.parent.color;
x.parent.color = 0;
s.right.color = 0;
leftRotate(x.parent);
x = root;
}
} else {
s = x.parent.left;
if (s.color == 1) {
s.color = 0;
x.parent.color = 1;
rightRotate(x.parent);
s = x.parent.left;
}

if (s.right.color == 0 && s.right.color == 0) {
s.color = 1;
x = x.parent;
} else {
if (s.left.color == 0) {
s.right.color = 0;
s.color = 1;
leftRotate(s);
s = x.parent.left;
}

s.color = x.parent.color;
x.parent.color = 0;
s.left.color = 0;
rightRotate(x.parent);
x = root;
}
}
}
x.color = 0;
}

private void rbTransplant(Node u, Node v) {
if (u.parent == null) {
root = v;
} else if (u == u.parent.left) {
u.parent.left = v;
} else {
u.parent.right = v;
}
v.parent = u.parent;
}

private void deleteNodeHelper(Node node, int key) {
Node z = TNULL;
Node x, y;
while (node != TNULL) {
if (node.data == key) {
z = node;
}

if (node.data <= key) {
node = node.right;
} else {
node = node.left;
}
}

if (z == TNULL) {
System.out.println("Couldn't find key in the tree");
return;
}

y = z;
int yOriginalColor = y.color;
if (z.left == TNULL) {
x = z.right;
rbTransplant(z, z.right);
} else if (z.right == TNULL) {
x = z.left;
rbTransplant(z, z.left);
} else {
y = minimum(z.right);
yOriginalColor = y.color;
x = y.right;
if (y.parent == z) {
x.parent = y;
} else {
rbTransplant(y, y.right);
y.right = z.right;
y.right.parent = y;
}

rbTransplant(z, y);
y.left = z.left;
y.left.parent = y;
y.color = z.color;
}
if (yOriginalColor == 0) {
fixDelete(x);
}
}

private void fixInsert(Node k) {
Node u;
while (k.parent.color == 1) {
if (k.parent == k.parent.parent.right) {
u = k.parent.parent.left;
if (u.color == 1) {
u.color = 0;
k.parent.color = 0;
k.parent.parent.color = 1;
k = k.parent.parent;
} else {
if (k == k.parent.left) {
k = k.parent;
rightRotate(k);
}
k.parent.color = 0;
k.parent.parent.color = 1;
leftRotate(k.parent.parent);
}
} else {
u = k.parent.parent.right;

if (u.color == 1) {
u.color = 0;
k.parent.color = 0;
k.parent.parent.color = 1;
k = k.parent.parent;
} else {
if (k == k.parent.right) {
k = k.parent;
leftRotate(k);
}
k.parent.color = 0;
k.parent.parent.color = 1;
rightRotate(k.parent.parent);
}
}
if (k == root) {
break;
}
}
root.color = 0;
}

private void printHelper(Node root, String indent, boolean last) {
if (root != TNULL) {
System.out.print(indent);
if (last) {
System.out.print("R----");
indent += "   ";
} else {
System.out.print("L----");
indent += "|  ";
}

String sColor = root.color == 1 ? "RED" : "BLACK";
System.out.println(root.data + "(" + sColor + ")");
printHelper(root.left, indent, false);
printHelper(root.right, indent, true);
}
}

public RedBlackTree() {
TNULL = new Node();
TNULL.color = 0;
TNULL.left = null;
TNULL.right = null;
root = TNULL;
}

public void preorder() {
preOrderHelper(this.root);
}

public void inorder() {
inOrderHelper(this.root);
}

public void postorder() {
postOrderHelper(this.root);
}

public Node searchTree(int k) {
return searchTreeHelper(this.root, k);
}

public Node minimum(Node node) {
while (node.left != TNULL) {
node = node.left;
}
return node;
}

public Node maximum(Node node) {
while (node.right != TNULL) {
node = node.right;
}
return node;
}

public Node successor(Node x) {
if (x.right != TNULL) {
return minimum(x.right);
}

Node y = x.parent;
while (y != TNULL && x == y.right) {
x = y;
y = y.parent;
}
return y;
}

public Node predecessor(Node x) {
if (x.left != TNULL) {
return maximum(x.left);
}

Node y = x.parent;
while (y != TNULL && x == y.left) {
x = y;
y = y.parent;
}

return y;
}

public void leftRotate(Node x) {
Node y = x.right;
x.right = y.left;
if (y.left != TNULL) {
y.left.parent = x;
}
y.parent = x.parent;
if (x.parent == null) {
this.root = y;
} else if (x == x.parent.left) {
x.parent.left = y;
} else {
x.parent.right = y;
}
y.left = x;
x.parent = y;
}

public void rightRotate(Node x) {
Node y = x.left;
x.left = y.right;
if (y.right != TNULL) {
y.right.parent = x;
}
y.parent = x.parent;
if (x.parent == null) {
this.root = y;
} else if (x == x.parent.right) {
x.parent.right = y;
} else {
x.parent.left = y;
}
y.right = x;
x.parent = y;
}

public void insert(int key) {
Node node = new Node();
node.parent = null;
node.data = key;
node.left = TNULL;
node.right = TNULL;
node.color = 1;

Node y = null;
Node x = this.root;

while (x != TNULL) {
y = x;
if (node.data < x.data) {
x = x.left;
} else {
x = x.right;
}
}

node.parent = y;
if (y == null) {
root = node;
} else if (node.data < y.data) {
y.left = node;
} else {
y.right = node;
}

if (node.parent == null) {
node.color = 0;
return;
}

if (node.parent.parent == null) {
return;
}

fixInsert(node);
}

public Node getRoot() {
return this.root;
}

public void deleteNode(int data) {
deleteNodeHelper(this.root, data);
}

public void printTree() {
printHelper(this.root, "", true);
}

public static void main(String[] args) {
RedBlackTree bst = new RedBlackTree();
bst.insert(55);
bst.insert(40);
bst.insert(65);
bst.insert(60);
bst.insert(75);
bst.insert(57);
bst.printTree();

System.out.println("\nAfter deleting:");
bst.deleteNode(40);
bst.printTree();
}
}
// Implementing Red-Black Tree in C

#include <stdio.h>
#include <stdlib.h>

enum nodeColor
{
RED,
BLACK
};

struct rbNode
{
int data, color;
};

struct rbNode *root = NULL;

struct rbNode *createNode(int data)
{
struct rbNode *newnode;
newnode = (struct rbNode *)malloc(sizeof(struct rbNode));
newnode->data = data;
newnode->color = RED;
return newnode;
}

void insertion(int data)
{
struct rbNode *stack[98], *ptr, *newnode, *xPtr, *yPtr;
int dir[98], ht = 0, index;
ptr = root;
if (!root)
{
root = createNode(data);
return;
}
stack[ht] = root;
dir[ht++] = 0;
while (ptr != NULL)
{
if (ptr->data == data)
{
printf("Duplicates Not Allowed!!\n");
return;
}
index = (data - ptr->data) > 0 ? 1 : 0;
stack[ht] = ptr;
dir[ht++] = index;
}
stack[ht - 1]->link[index] = newnode = createNode(data);
while ((ht >= 3) && (stack[ht - 1]->color == RED))
{
if (dir[ht - 2] == 0)
{
if (yPtr != NULL && yPtr->color == RED)
{
stack[ht - 2]->color = RED;
stack[ht - 1]->color = yPtr->color = BLACK;
ht = ht - 2;
}
else
{
if (dir[ht - 1] == 0)
{
yPtr = stack[ht - 1];
}
else
{
xPtr = stack[ht - 1];
}
xPtr = stack[ht - 2];
xPtr->color = RED;
yPtr->color = BLACK;
if (xPtr == root)
{
root = yPtr;
}
else
{
stack[ht - 3]->link[dir[ht - 3]] = yPtr;
}
break;
}
}
else
{
if ((yPtr != NULL) && (yPtr->color == RED))
{
stack[ht - 2]->color = RED;
stack[ht - 1]->color = yPtr->color = BLACK;
ht = ht - 2;
}
else
{
if (dir[ht - 1] == 1)
{
yPtr = stack[ht - 1];
}
else
{
xPtr = stack[ht - 1];
}
xPtr = stack[ht - 2];
yPtr->color = BLACK;
xPtr->color = RED;
if (xPtr == root)
{
root = yPtr;
}
else
{
stack[ht - 3]->link[dir[ht - 3]] = yPtr;
}
break;
}
}
}
root->color = BLACK;
}

void deletion(int data)
{
struct rbNode *stack[98], *ptr, *xPtr, *yPtr;
struct rbNode *pPtr, *qPtr, *rPtr;
int dir[98], ht = 0, diff, i;
enum nodeColor color;

if (!root)
{
printf("Tree not available\n");
return;
}

ptr = root;
while (ptr != NULL)
{
if ((data - ptr->data) == 0)
break;
diff = (data - ptr->data) > 0 ? 1 : 0;
stack[ht] = ptr;
dir[ht++] = diff;
}

{
if ((ptr == root) && (ptr->link[0] == NULL))
{
free(ptr);
root = NULL;
}
else if (ptr == root)
{
free(ptr);
}
else
{
}
}
else
{
{
color = xPtr->color;
xPtr->color = ptr->color;
ptr->color = color;

if (ptr == root)
{
root = xPtr;
}
else
{
stack[ht - 1]->link[dir[ht - 1]] = xPtr;
}

dir[ht] = 1;
stack[ht++] = xPtr;
}
else
{
i = ht++;
while (1)
{
dir[ht] = 0;
stack[ht++] = xPtr;
break;
xPtr = yPtr;
}

dir[i] = 1;
stack[i] = yPtr;
if (i > 0)
stack[i - 1]->link[dir[i - 1]] = yPtr;

if (ptr == root)
{
root = yPtr;
}

color = yPtr->color;
yPtr->color = ptr->color;
ptr->color = color;
}
}
if (ht < 1)
return;
if (ptr->color == BLACK)
{
while (1)
{
pPtr = stack[ht - 1]->link[dir[ht - 1]];
if (pPtr && pPtr->color == RED)
{
pPtr->color = BLACK;
break;
}

if (ht < 2)
break;

if (dir[ht - 2] == 0)
{

if (!rPtr)
break;

if (rPtr->color == RED)
{
stack[ht - 1]->color = RED;
rPtr->color = BLACK;

if (stack[ht - 1] == root)
{
root = rPtr;
}
else
{
stack[ht - 2]->link[dir[ht - 2]] = rPtr;
}
dir[ht] = 0;
stack[ht] = stack[ht - 1];
stack[ht - 1] = rPtr;
ht++;

}

{
rPtr->color = RED;
}
else
{
{
rPtr->color = RED;
qPtr->color = BLACK;
rPtr = stack[ht - 1]->link[1] = qPtr;
}
rPtr->color = stack[ht - 1]->color;
stack[ht - 1]->color = BLACK;
if (stack[ht - 1] == root)
{
root = rPtr;
}
else
{
stack[ht - 2]->link[dir[ht - 2]] = rPtr;
}
break;
}
}
else
{
if (!rPtr)
break;

if (rPtr->color == RED)
{
stack[ht - 1]->color = RED;
rPtr->color = BLACK;

if (stack[ht - 1] == root)
{
root = rPtr;
}
else
{

stack[ht - 2]->link[dir[ht - 2]] = rPtr;
}
dir[ht] = 1;
stack[ht] = stack[ht - 1];
stack[ht - 1] = rPtr;
ht++;

}
{
rPtr->color = RED;
}
else
{
{
rPtr->color = RED;
qPtr->color = BLACK;
rPtr = stack[ht - 1]->link[0] = qPtr;
}
rPtr->color = stack[ht - 1]->color;
stack[ht - 1]->color = BLACK;
if (stack[ht - 1] == root)
{
root = rPtr;
}
else
{
stack[ht - 2]->link[dir[ht - 2]] = rPtr;
}
break;
}
}
ht--;
}
}
}

void inorderTraversal(struct rbNode *node)
{
if (node)
{
printf("%d  ", node->data);
}
return;
}

int main()
{
int ch, data;
while (1)
{
printf("1. Insertion\t2. Deletion\n");
printf("3. Traverse\t4. Exit");
scanf("%d", &ch);
switch (ch)
{
case 1:
printf("Enter the element to insert:");
scanf("%d", &data);
insertion(data);
break;
case 2:
printf("Enter the element to delete:");
scanf("%d", &data);
deletion(data);
break;
case 3:
inorderTraversal(root);
printf("\n");
break;
case 4:
exit(0);
default:
printf("Not available\n");
break;
}
printf("\n");
}
return 0;
}
// Implementing Red-Black Tree in C++

#include <iostream>
using namespace std;

struct Node
{
int data;
Node *parent;
Node *left;
Node *right;
int color;
};

typedef Node *NodePtr;

class RedBlackTree
{
private:
NodePtr root;
NodePtr TNULL;

void initializeNULLNode(NodePtr node, NodePtr parent)
{
node->data = 0;
node->parent = parent;
node->left = nullptr;
node->right = nullptr;
node->color = 0;
}

void preOrderHelper(NodePtr node)
{
if (node != TNULL)
{
cout << node->data << " ";
preOrderHelper(node->left);
preOrderHelper(node->right);
}
}

void inOrderHelper(NodePtr node)
{
if (node != TNULL)
{
inOrderHelper(node->left);
cout << node->data << " ";
inOrderHelper(node->right);
}
}

void postOrderHelper(NodePtr node)
{
if (node != TNULL)
{
postOrderHelper(node->left);
postOrderHelper(node->right);
cout << node->data << " ";
}
}

NodePtr searchTreeHelper(NodePtr node, int key)
{
if (node == TNULL || key == node->data)
{
return node;
}

if (key < node->data)
{
return searchTreeHelper(node->left, key);
}
return searchTreeHelper(node->right, key);
}

void deleteFix(NodePtr x)
{
NodePtr s;
while (x != root && x->color == 0)
{
if (x == x->parent->left)
{
s = x->parent->right;
if (s->color == 1)
{
s->color = 0;
x->parent->color = 1;
leftRotate(x->parent);
s = x->parent->right;
}

if (s->left->color == 0 && s->right->color == 0)
{
s->color = 1;
x = x->parent;
}
else
{
if (s->right->color == 0)
{
s->left->color = 0;
s->color = 1;
rightRotate(s);
s = x->parent->right;
}

s->color = x->parent->color;
x->parent->color = 0;
s->right->color = 0;
leftRotate(x->parent);
x = root;
}
}
else
{
s = x->parent->left;
if (s->color == 1)
{
s->color = 0;
x->parent->color = 1;
rightRotate(x->parent);
s = x->parent->left;
}

if (s->right->color == 0 && s->right->color == 0)
{
s->color = 1;
x = x->parent;
}
else
{
if (s->left->color == 0)
{
s->right->color = 0;
s->color = 1;
leftRotate(s);
s = x->parent->left;
}

s->color = x->parent->color;
x->parent->color = 0;
s->left->color = 0;
rightRotate(x->parent);
x = root;
}
}
}
x->color = 0;
}

void rbTransplant(NodePtr u, NodePtr v)
{
if (u->parent == nullptr)
{
root = v;
}
else if (u == u->parent->left)
{
u->parent->left = v;
}
else
{
u->parent->right = v;
}
v->parent = u->parent;
}

void deleteNodeHelper(NodePtr node, int key)
{
NodePtr z = TNULL;
NodePtr x, y;
while (node != TNULL)
{
if (node->data == key)
{
z = node;
}

if (node->data <= key)
{
node = node->right;
}
else
{
node = node->left;
}
}

if (z == TNULL)
{
return;
}

y = z;
int y_original_color = y->color;
if (z->left == TNULL)
{
x = z->right;
rbTransplant(z, z->right);
}
else if (z->right == TNULL)
{
x = z->left;
rbTransplant(z, z->left);
}
else
{
y = minimum(z->right);
y_original_color = y->color;
x = y->right;
if (y->parent == z)
{
x->parent = y;
}
else
{
rbTransplant(y, y->right);
y->right = z->right;
y->right->parent = y;
}

rbTransplant(z, y);
y->left = z->left;
y->left->parent = y;
y->color = z->color;
}
delete z;
if (y_original_color == 0)
{
deleteFix(x);
}
}

void insertFix(NodePtr k)
{
NodePtr u;
while (k->parent->color == 1)
{
if (k->parent == k->parent->parent->right)
{
u = k->parent->parent->left;
if (u->color == 1)
{
u->color = 0;
k->parent->color = 0;
k->parent->parent->color = 1;
k = k->parent->parent;
}
else
{
if (k == k->parent->left)
{
k = k->parent;
rightRotate(k);
}
k->parent->color = 0;
k->parent->parent->color = 1;
leftRotate(k->parent->parent);
}
}
else
{
u = k->parent->parent->right;

if (u->color == 1)
{
u->color = 0;
k->parent->color = 0;
k->parent->parent->color = 1;
k = k->parent->parent;
}
else
{
if (k == k->parent->right)
{
k = k->parent;
leftRotate(k);
}
k->parent->color = 0;
k->parent->parent->color = 1;
rightRotate(k->parent->parent);
}
}
if (k == root)
{
break;
}
}
root->color = 0;
}

void printHelper(NodePtr root, string indent, bool last)
{
if (root != TNULL)
{
cout << indent;
if (last)
{
cout << "R----";
indent += "   ";
}
else
{
cout << "L----";
indent += "|  ";
}

string sColor = root->color ? "RED" : "BLACK";
cout << root->data << "(" << sColor << ")" << endl;
printHelper(root->left, indent, false);
printHelper(root->right, indent, true);
}
}

public:
RedBlackTree()
{
TNULL = new Node;
TNULL->color = 0;
TNULL->left = nullptr;
TNULL->right = nullptr;
root = TNULL;
}

void preorder()
{
preOrderHelper(this->root);
}

void inorder()
{
inOrderHelper(this->root);
}

void postorder()
{
postOrderHelper(this->root);
}

NodePtr searchTree(int k)
{
return searchTreeHelper(this->root, k);
}

NodePtr minimum(NodePtr node)
{
while (node->left != TNULL)
{
node = node->left;
}
return node;
}

NodePtr maximum(NodePtr node)
{
while (node->right != TNULL)
{
node = node->right;
}
return node;
}

NodePtr successor(NodePtr x)
{
if (x->right != TNULL)
{
return minimum(x->right);
}

NodePtr y = x->parent;
while (y != TNULL && x == y->right)
{
x = y;
y = y->parent;
}
return y;
}

NodePtr predecessor(NodePtr x)
{
if (x->left != TNULL)
{
return maximum(x->left);
}

NodePtr y = x->parent;
while (y != TNULL && x == y->left)
{
x = y;
y = y->parent;
}

return y;
}

void leftRotate(NodePtr x)
{
NodePtr y = x->right;
x->right = y->left;
if (y->left != TNULL)
{
y->left->parent = x;
}
y->parent = x->parent;
if (x->parent == nullptr)
{
this->root = y;
}
else if (x == x->parent->left)
{
x->parent->left = y;
}
else
{
x->parent->right = y;
}
y->left = x;
x->parent = y;
}

void rightRotate(NodePtr x)
{
NodePtr y = x->left;
x->left = y->right;
if (y->right != TNULL)
{
y->right->parent = x;
}
y->parent = x->parent;
if (x->parent == nullptr)
{
this->root = y;
}
else if (x == x->parent->right)
{
x->parent->right = y;
}
else
{
x->parent->left = y;
}
y->right = x;
x->parent = y;
}

void insert(int key)
{
NodePtr node = new Node;
node->parent = nullptr;
node->data = key;
node->left = TNULL;
node->right = TNULL;
node->color = 1;

NodePtr y = nullptr;
NodePtr x = this->root;

while (x != TNULL)
{
y = x;
if (node->data < x->data)
{
x = x->left;
}
else
{
x = x->right;
}
}

node->parent = y;
if (y == nullptr)
{
root = node;
}
else if (node->data < y->data)
{
y->left = node;
}
else
{
y->right = node;
}

if (node->parent == nullptr)
{
node->color = 0;
return;
}

if (node->parent->parent == nullptr)
{
return;
}

insertFix(node);
}

NodePtr getRoot()
{
return this->root;
}

void deleteNode(int data)
{
deleteNodeHelper(this->root, data);
}

void printTree()
{
if (root)
{
printHelper(this->root, "", true);
}
}
};

int main()
{
RedBlackTree bst;
bst.insert(55);
bst.insert(40);
bst.insert(65);
bst.insert(60);
bst.insert(75);
bst.insert(57);

bst.printTree();
cout << endl
<< "After deleting" << endl;
bst.deleteNode(40);
bst.printTree();
}