原文: https://www.programiz.com/dsa/insertion-in-a-red-black-tree

在本教程中,您将学习如何将新节点插入到红黑树中。 此外,您还将找到在 C,C++ ,Java 和 Python 的红黑树上执行插入的工作示例。

红黑树是一种自平衡二叉搜索树,其中每个节点都包含一个额外的位,用于表示该节点的颜色,红色还是黑色。

阅读本文之前,请参考红黑树上的文章。

插入新节点时,新节点始终作为红色节点插入。 插入新节点后,如果树违反了红黑树的属性,则执行以下操作。

  1. 重新着色
  2. 重新旋转

插入新节点的算法

按照以下步骤将新元素插入到红黑树中:

  1. newNode为:
    插入红黑树 - 图1
    新节点

  2. y为叶子(即NIL),x为树的根。 新节点将插入下面的树中。
    插入红黑树 - 图2
    初始树

  3. 检查树是否为空(即x是否为NIL)。 如果是,请插入newNode作为根节点,并将其着色为黑色。

  4. 否则,请重复以下步骤,直到达到叶子(NIL)。

    1. 比较newKeyrootKey

    2. 如果newKey大于rootKey,则遍历右侧子树。

    3. 否则,遍历左子树。
      插入红黑树 - 图3
      指向要在其中插入newNode的节点的路径

  5. 将叶子的父级分配为newNode的父级。

  6. 如果leafKey大于newKey,则将newNode设为rightChild

  7. 否则,将newNode设置为leftChild
    插入红黑树 - 图4
    插入了新节点

  8. 在左侧分配NULL,在newNode分配rightChild

  9. newNode分配红色。
    插入红黑树 - 图5
    newNode的颜色设置为红色,并为子代分配空值

  10. 调用InsertFix算法来维护红黑树的属性(如果违反)。


为什么新插入的节点在红黑树中总是红色?

这是因为插入红色节点不会违反红黑树的depth属性。

如果将红色节点附加到红色节点,则会违反该规则,但是比通过违反depth属性引入的问题更容易解决此问题。


插入后保持红黑属性的算法

如果插入newNode违反了该属性,则此算法用于维护红黑树的属性。

  1. 执行以下操作,直到newNode p的父代变为红色。

  2. 如果pnewNodegrandParent gP的左子级,请执行以下操作。
    情况一

    1. 如果newNodegP的右子级的颜色是红色,则将gP的子级的颜色都设置为黑色,将gP的颜色都设置为红色。
      插入红黑树 - 图6
      颜色更改

    2. gP分配给newNode
      插入红黑树 - 图7
      重新分配newNode
      情况 II

    3. (在继续此步骤之前,将检查while循环。如果不满足条件,则循环会中断。)
      否则,如果newNodep的右子代,则将p分配给[ newNode
      插入红黑树 - 图8
      newNode的父级分配为newNode

    4. 左旋转newNode
      插入红黑树 - 图9
      左旋转
      情况 III

    5. (在继续此步骤之前,检查循环。如果不满足条件,则循环中断。)
      p的颜色设置为黑色,将gP的颜色设置为红色。
      插入红黑树 - 图10
      颜色更改

    6. 向右旋转gP
      插入红黑树 - 图11
      右旋

  3. 否则,请执行以下操作。

    1. 如果zgP的左子项的颜色是红色,请将gP的子项的颜色都设置为黑色,将gP的颜色都设置为红色。
    2. gP分配给newNode
    3. 否则,如果newNodep的左子代,则将p分配给newNode并向右旋转newNode
    4. p的颜色设置为黑色,将gP的颜色设置为红色。
    5. 左旋转gP
  4. (从while循环中退出后执行此步骤。)
    将树的根设置为黑色。
    插入红黑树 - 图12
    将根的颜色设置为黑色

最终的树如下所示:

插入红黑树 - 图13

最终的树


Python,Java 和 C/C++ 示例

  1. # Implementing Red-Black Tree in Python
  2. import sys
  3. # Node creation
  4. class Node():
  5. def __init__(self, item):
  6. self.item = item
  7. self.parent = None
  8. self.left = None
  9. self.right = None
  10. self.color = 1
  11. class RedBlackTree():
  12. def __init__(self):
  13. self.TNULL = Node(0)
  14. self.TNULL.color = 0
  15. self.TNULL.left = None
  16. self.TNULL.right = None
  17. self.root = self.TNULL
  18. # Preorder
  19. def pre_order_helper(self, node):
  20. if node != TNULL:
  21. sys.stdout.write(node.item + " ")
  22. self.pre_order_helper(node.left)
  23. self.pre_order_helper(node.right)
  24. # Inorder
  25. def in_order_helper(self, node):
  26. if node != TNULL:
  27. self.in_order_helper(node.left)
  28. sys.stdout.write(node.item + " ")
  29. self.in_order_helper(node.right)
  30. # Postorder
  31. def post_order_helper(self, node):
  32. if node != TNULL:
  33. self.post_order_helper(node.left)
  34. self.post_order_helper(node.right)
  35. sys.stdout.write(node.item + " ")
  36. # Search the tree
  37. def search_tree_helper(self, node, key):
  38. if node == TNULL or key == node.item:
  39. return node
  40. if key < node.item:
  41. return self.search_tree_helper(node.left, key)
  42. return self.search_tree_helper(node.right, key)
  43. # Balance the tree after insertion
  44. def fix_insert(self, k):
  45. while k.parent.color == 1:
  46. if k.parent == k.parent.parent.right:
  47. u = k.parent.parent.left
  48. if u.color == 1:
  49. u.color = 0
  50. k.parent.color = 0
  51. k.parent.parent.color = 1
  52. k = k.parent.parent
  53. else:
  54. if k == k.parent.left:
  55. k = k.parent
  56. self.right_rotate(k)
  57. k.parent.color = 0
  58. k.parent.parent.color = 1
  59. self.left_rotate(k.parent.parent)
  60. else:
  61. u = k.parent.parent.right
  62. if u.color == 1:
  63. u.color = 0
  64. k.parent.color = 0
  65. k.parent.parent.color = 1
  66. k = k.parent.parent
  67. else:
  68. if k == k.parent.right:
  69. k = k.parent
  70. self.left_rotate(k)
  71. k.parent.color = 0
  72. k.parent.parent.color = 1
  73. self.right_rotate(k.parent.parent)
  74. if k == self.root:
  75. break
  76. self.root.color = 0
  77. # Printing the tree
  78. def __print_helper(self, node, indent, last):
  79. if node != self.TNULL:
  80. sys.stdout.write(indent)
  81. if last:
  82. sys.stdout.write("R----")
  83. indent += " "
  84. else:
  85. sys.stdout.write("L----")
  86. indent += "| "
  87. s_color = "RED" if node.color == 1 else "BLACK"
  88. print(str(node.item) + "(" + s_color + ")")
  89. self.__print_helper(node.left, indent, False)
  90. self.__print_helper(node.right, indent, True)
  91. def preorder(self):
  92. self.pre_order_helper(self.root)
  93. def inorder(self):
  94. self.in_order_helper(self.root)
  95. def postorder(self):
  96. self.post_order_helper(self.root)
  97. def searchTree(self, k):
  98. return self.search_tree_helper(self.root, k)
  99. def minimum(self, node):
  100. while node.left != self.TNULL:
  101. node = node.left
  102. return node
  103. def maximum(self, node):
  104. while node.right != self.TNULL:
  105. node = node.right
  106. return node
  107. def successor(self, x):
  108. if x.right != self.TNULL:
  109. return self.minimum(x.right)
  110. y = x.parent
  111. while y != self.TNULL and x == y.right:
  112. x = y
  113. y = y.parent
  114. return y
  115. def predecessor(self, x):
  116. if (x.left != self.TNULL):
  117. return self.maximum(x.left)
  118. y = x.parent
  119. while y != self.TNULL and x == y.left:
  120. x = y
  121. y = y.parent
  122. return y
  123. def left_rotate(self, x):
  124. y = x.right
  125. x.right = y.left
  126. if y.left != self.TNULL:
  127. y.left.parent = x
  128. y.parent = x.parent
  129. if x.parent == None:
  130. self.root = y
  131. elif x == x.parent.left:
  132. x.parent.left = y
  133. else:
  134. x.parent.right = y
  135. y.left = x
  136. x.parent = y
  137. def right_rotate(self, x):
  138. y = x.left
  139. x.left = y.right
  140. if y.right != self.TNULL:
  141. y.right.parent = x
  142. y.parent = x.parent
  143. if x.parent == None:
  144. self.root = y
  145. elif x == x.parent.right:
  146. x.parent.right = y
  147. else:
  148. x.parent.left = y
  149. y.right = x
  150. x.parent = y
  151. def insert(self, key):
  152. node = Node(key)
  153. node.parent = None
  154. node.item = key
  155. node.left = self.TNULL
  156. node.right = self.TNULL
  157. node.color = 1
  158. y = None
  159. x = self.root
  160. while x != self.TNULL:
  161. y = x
  162. if node.item < x.item:
  163. x = x.left
  164. else:
  165. x = x.right
  166. node.parent = y
  167. if y == None:
  168. self.root = node
  169. elif node.item < y.item:
  170. y.left = node
  171. else:
  172. y.right = node
  173. if node.parent == None:
  174. node.color = 0
  175. return
  176. if node.parent.parent == None:
  177. return
  178. self.fix_insert(node)
  179. def get_root(self):
  180. return self.root
  181. def print_tree(self):
  182. self.__print_helper(self.root, "", True)
  183. if __name__ == "__main__":
  184. bst = RedBlackTree()
  185. bst.insert(55)
  186. bst.insert(40)
  187. bst.insert(65)
  188. bst.insert(60)
  189. bst.insert(75)
  190. bst.insert(57)
  191. bst.print_tree()
  1. // Implementing Red-Black Tree in Java
  2. class Node {
  3. int data;
  4. Node parent;
  5. Node left;
  6. Node right;
  7. int color;
  8. }
  9. public class RedBlackTree {
  10. private Node root;
  11. private Node TNULL;
  12. // Preorder
  13. private void preOrderHelper(Node node) {
  14. if (node != TNULL) {
  15. System.out.print(node.data + " ");
  16. preOrderHelper(node.left);
  17. preOrderHelper(node.right);
  18. }
  19. }
  20. // Inorder
  21. private void inOrderHelper(Node node) {
  22. if (node != TNULL) {
  23. inOrderHelper(node.left);
  24. System.out.print(node.data + " ");
  25. inOrderHelper(node.right);
  26. }
  27. }
  28. // Post order
  29. private void postOrderHelper(Node node) {
  30. if (node != TNULL) {
  31. postOrderHelper(node.left);
  32. postOrderHelper(node.right);
  33. System.out.print(node.data + " ");
  34. }
  35. }
  36. // Search the tree
  37. private Node searchTreeHelper(Node node, int key) {
  38. if (node == TNULL || key == node.data) {
  39. return node;
  40. }
  41. if (key < node.data) {
  42. return searchTreeHelper(node.left, key);
  43. }
  44. return searchTreeHelper(node.right, key);
  45. }
  46. // Balance the tree after deletion of a node
  47. private void fixDelete(Node x) {
  48. Node s;
  49. while (x != root && x.color == 0) {
  50. if (x == x.parent.left) {
  51. s = x.parent.right;
  52. if (s.color == 1) {
  53. s.color = 0;
  54. x.parent.color = 1;
  55. leftRotate(x.parent);
  56. s = x.parent.right;
  57. }
  58. if (s.left.color == 0 && s.right.color == 0) {
  59. s.color = 1;
  60. x = x.parent;
  61. } else {
  62. if (s.right.color == 0) {
  63. s.left.color = 0;
  64. s.color = 1;
  65. rightRotate(s);
  66. s = x.parent.right;
  67. }
  68. s.color = x.parent.color;
  69. x.parent.color = 0;
  70. s.right.color = 0;
  71. leftRotate(x.parent);
  72. x = root;
  73. }
  74. } else {
  75. s = x.parent.left;
  76. if (s.color == 1) {
  77. s.color = 0;
  78. x.parent.color = 1;
  79. rightRotate(x.parent);
  80. s = x.parent.left;
  81. }
  82. if (s.right.color == 0 && s.right.color == 0) {
  83. s.color = 1;
  84. x = x.parent;
  85. } else {
  86. if (s.left.color == 0) {
  87. s.right.color = 0;
  88. s.color = 1;
  89. leftRotate(s);
  90. s = x.parent.left;
  91. }
  92. s.color = x.parent.color;
  93. x.parent.color = 0;
  94. s.left.color = 0;
  95. rightRotate(x.parent);
  96. x = root;
  97. }
  98. }
  99. }
  100. x.color = 0;
  101. }
  102. private void rbTransplant(Node u, Node v) {
  103. if (u.parent == null) {
  104. root = v;
  105. } else if (u == u.parent.left) {
  106. u.parent.left = v;
  107. } else {
  108. u.parent.right = v;
  109. }
  110. v.parent = u.parent;
  111. }
  112. // Balance the node after insertion
  113. private void fixInsert(Node k) {
  114. Node u;
  115. while (k.parent.color == 1) {
  116. if (k.parent == k.parent.parent.right) {
  117. u = k.parent.parent.left;
  118. if (u.color == 1) {
  119. u.color = 0;
  120. k.parent.color = 0;
  121. k.parent.parent.color = 1;
  122. k = k.parent.parent;
  123. } else {
  124. if (k == k.parent.left) {
  125. k = k.parent;
  126. rightRotate(k);
  127. }
  128. k.parent.color = 0;
  129. k.parent.parent.color = 1;
  130. leftRotate(k.parent.parent);
  131. }
  132. } else {
  133. u = k.parent.parent.right;
  134. if (u.color == 1) {
  135. u.color = 0;
  136. k.parent.color = 0;
  137. k.parent.parent.color = 1;
  138. k = k.parent.parent;
  139. } else {
  140. if (k == k.parent.right) {
  141. k = k.parent;
  142. leftRotate(k);
  143. }
  144. k.parent.color = 0;
  145. k.parent.parent.color = 1;
  146. rightRotate(k.parent.parent);
  147. }
  148. }
  149. if (k == root) {
  150. break;
  151. }
  152. }
  153. root.color = 0;
  154. }
  155. private void printHelper(Node root, String indent, boolean last) {
  156. if (root != TNULL) {
  157. System.out.print(indent);
  158. if (last) {
  159. System.out.print("R----");
  160. indent += " ";
  161. } else {
  162. System.out.print("L----");
  163. indent += "| ";
  164. }
  165. String sColor = root.color == 1 ? "RED" : "BLACK";
  166. System.out.println(root.data + "(" + sColor + ")");
  167. printHelper(root.left, indent, false);
  168. printHelper(root.right, indent, true);
  169. }
  170. }
  171. public RedBlackTree() {
  172. TNULL = new Node();
  173. TNULL.color = 0;
  174. TNULL.left = null;
  175. TNULL.right = null;
  176. root = TNULL;
  177. }
  178. public void preorder() {
  179. preOrderHelper(this.root);
  180. }
  181. public void inorder() {
  182. inOrderHelper(this.root);
  183. }
  184. public void postorder() {
  185. postOrderHelper(this.root);
  186. }
  187. public Node searchTree(int k) {
  188. return searchTreeHelper(this.root, k);
  189. }
  190. public Node minimum(Node node) {
  191. while (node.left != TNULL) {
  192. node = node.left;
  193. }
  194. return node;
  195. }
  196. public Node maximum(Node node) {
  197. while (node.right != TNULL) {
  198. node = node.right;
  199. }
  200. return node;
  201. }
  202. public Node successor(Node x) {
  203. if (x.right != TNULL) {
  204. return minimum(x.right);
  205. }
  206. Node y = x.parent;
  207. while (y != TNULL && x == y.right) {
  208. x = y;
  209. y = y.parent;
  210. }
  211. return y;
  212. }
  213. public Node predecessor(Node x) {
  214. if (x.left != TNULL) {
  215. return maximum(x.left);
  216. }
  217. Node y = x.parent;
  218. while (y != TNULL && x == y.left) {
  219. x = y;
  220. y = y.parent;
  221. }
  222. return y;
  223. }
  224. public void leftRotate(Node x) {
  225. Node y = x.right;
  226. x.right = y.left;
  227. if (y.left != TNULL) {
  228. y.left.parent = x;
  229. }
  230. y.parent = x.parent;
  231. if (x.parent == null) {
  232. this.root = y;
  233. } else if (x == x.parent.left) {
  234. x.parent.left = y;
  235. } else {
  236. x.parent.right = y;
  237. }
  238. y.left = x;
  239. x.parent = y;
  240. }
  241. public void rightRotate(Node x) {
  242. Node y = x.left;
  243. x.left = y.right;
  244. if (y.right != TNULL) {
  245. y.right.parent = x;
  246. }
  247. y.parent = x.parent;
  248. if (x.parent == null) {
  249. this.root = y;
  250. } else if (x == x.parent.right) {
  251. x.parent.right = y;
  252. } else {
  253. x.parent.left = y;
  254. }
  255. y.right = x;
  256. x.parent = y;
  257. }
  258. public void insert(int key) {
  259. Node node = new Node();
  260. node.parent = null;
  261. node.data = key;
  262. node.left = TNULL;
  263. node.right = TNULL;
  264. node.color = 1;
  265. Node y = null;
  266. Node x = this.root;
  267. while (x != TNULL) {
  268. y = x;
  269. if (node.data < x.data) {
  270. x = x.left;
  271. } else {
  272. x = x.right;
  273. }
  274. }
  275. node.parent = y;
  276. if (y == null) {
  277. root = node;
  278. } else if (node.data < y.data) {
  279. y.left = node;
  280. } else {
  281. y.right = node;
  282. }
  283. if (node.parent == null) {
  284. node.color = 0;
  285. return;
  286. }
  287. if (node.parent.parent == null) {
  288. return;
  289. }
  290. fixInsert(node);
  291. }
  292. public Node getRoot() {
  293. return this.root;
  294. }
  295. public void printTree() {
  296. printHelper(this.root, "", true);
  297. }
  298. public static void main(String[] args) {
  299. RedBlackTree bst = new RedBlackTree();
  300. bst.insert(55);
  301. bst.insert(40);
  302. bst.insert(65);
  303. bst.insert(60);
  304. bst.insert(75);
  305. bst.insert(57);
  306. bst.printTree();
  307. }
  308. }
// Implementing Red-Black Tree in C

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

enum nodeColor {
  RED,
  BLACK
};

struct rbNode {
  int data, color;
  struct rbNode *link[2];
};

struct rbNode *root = NULL;

// Create a red-black tree
struct rbNode *createNode(int data) {
  struct rbNode *newnode;
  newnode = (struct rbNode *)malloc(sizeof(struct rbNode));
  newnode->data = data;
  newnode->color = RED;
  newnode->link[0] = newnode->link[1] = NULL;
  return newnode;
}

// Insert an node
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;
    ptr = ptr->link[index];
    dir[ht++] = index;
  }
  stack[ht - 1]->link[index] = newnode = createNode(data);
  while ((ht >= 3) && (stack[ht - 1]->color == RED)) {
    if (dir[ht - 2] == 0) {
      yPtr = stack[ht - 2]->link[1];
      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];
          yPtr = xPtr->link[1];
          xPtr->link[1] = yPtr->link[0];
          yPtr->link[0] = xPtr;
          stack[ht - 2]->link[0] = yPtr;
        }
        xPtr = stack[ht - 2];
        xPtr->color = RED;
        yPtr->color = BLACK;
        xPtr->link[0] = yPtr->link[1];
        yPtr->link[1] = xPtr;
        if (xPtr == root) {
          root = yPtr;
        } else {
          stack[ht - 3]->link[dir[ht - 3]] = yPtr;
        }
        break;
      }
    } else {
      yPtr = stack[ht - 2]->link[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] == 1) {
          yPtr = stack[ht - 1];
        } else {
          xPtr = stack[ht - 1];
          yPtr = xPtr->link[0];
          xPtr->link[0] = yPtr->link[1];
          yPtr->link[1] = xPtr;
          stack[ht - 2]->link[1] = yPtr;
        }
        xPtr = stack[ht - 2];
        yPtr->color = BLACK;
        xPtr->color = RED;
        xPtr->link[1] = yPtr->link[0];
        yPtr->link[0] = xPtr;
        if (xPtr == root) {
          root = yPtr;
        } else {
          stack[ht - 3]->link[dir[ht - 3]] = yPtr;
        }
        break;
      }
    }
  }
  root->color = BLACK;
}

// Delete a node
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;
    ptr = ptr->link[diff];
  }

  if (ptr->link[1] == NULL) {
    if ((ptr == root) && (ptr->link[0] == NULL)) {
      free(ptr);
      root = NULL;
    } else if (ptr == root) {
      root = ptr->link[0];
      free(ptr);
    } else {
      stack[ht - 1]->link[dir[ht - 1]] = ptr->link[0];
    }
  } else {
    xPtr = ptr->link[1];
    if (xPtr->link[0] == NULL) {
      xPtr->link[0] = ptr->link[0];
      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;
        yPtr = xPtr->link[0];
        if (!yPtr->link[0])
          break;
        xPtr = yPtr;
      }

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

      yPtr->link[0] = ptr->link[0];

      xPtr->link[0] = yPtr->link[1];
      yPtr->link[1] = ptr->link[1];

      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) {
        rPtr = stack[ht - 1]->link[1];

        if (!rPtr)
          break;

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

          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 = stack[ht - 1]->link[1];
        }

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

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

          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 = stack[ht - 1]->link[0];
        }
        if ((!rPtr->link[0] || rPtr->link[0]->color == BLACK) &&
          (!rPtr->link[1] || rPtr->link[1]->color == BLACK)) {
          rPtr->color = RED;
        } else {
          if (!rPtr->link[0] || rPtr->link[0]->color == BLACK) {
            qPtr = rPtr->link[1];
            rPtr->color = RED;
            qPtr->color = BLACK;
            rPtr->link[1] = qPtr->link[0];
            qPtr->link[0] = rPtr;
            rPtr = stack[ht - 1]->link[0] = qPtr;
          }
          rPtr->color = stack[ht - 1]->color;
          stack[ht - 1]->color = BLACK;
          rPtr->link[0]->color = BLACK;
          stack[ht - 1]->link[0] = rPtr->link[1];
          rPtr->link[1] = stack[ht - 1];
          if (stack[ht - 1] == root) {
            root = rPtr;
          } else {
            stack[ht - 2]->link[dir[ht - 2]] = rPtr;
          }
          break;
        }
      }
      ht--;
    }
  }
}

// Print the inorder traversal of the tree
void inorderTraversal(struct rbNode *node) {
  if (node) {
    inorderTraversal(node->link[0]);
    printf("%d  ", node->data);
    inorderTraversal(node->link[1]);
  }
  return;
}

// Driver code
int main() {
  int ch, data;
  while (1) {
    printf("1\. Insertion\t2\. Deletion\n");
    printf("3\. Traverse\t4\. Exit");
    printf("\nEnter your choice:");
    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;
  }

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

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

  // Post order
  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);
  }

  // For balancing the tree after deletion
  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) {
      cout << "Key not found in the tree" << endl;
      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);
    }
  }

  // For balancing the tree after insertion
  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;
  }

  // Inserting a node
  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();
}