There are three common operations for RBT: insertion, deletion, and search. Search was conducted like normal binary tree, while insertion and deletion require complex operation to make rule 3 is not violated.

The code for rotate-right operation would be like,

The rotate-right operation is similar with rotate-left, we just swap the left and right attribute with right and left .

The code for this operation would be like,

left node of right ( x.right.left or gleft ) become right node of x , replacing the x.right node itself.

Given x as node to be rotated, rotate-left will,

Insertion

Inserting a new node to RBT is just like normal binary tree, except for three things,

the color of new node always RED.

If new node has the same content with node in the tree, there are two condition that we could do (depends on programmer needs): replace them or go to the right node looking for empty leaf.

After node has been inserted, the whole tree color need to be fixed up.

Since new node will be at the bottom of the tree, fixing up the tree will be start from bottom until root, so its a loop condition. The loop will stop when these two conditions met,

when parent is black, or

node does not have grand-parent.

Based on these, we can start by creating insert-fixup function with loop,

static TreeNode* INSERT_FIXUP(TreeNode* root, TreeNode* node) { TreeNode* parent = NULL; TreeNode* gp = NULL; // grand parent; TreeNode* auth = NULL; // this is the sibling of node's parent. parent = node->get_parent(); while (parent && parent->is_red()) { gp = node->get_grand_parent(); if (!gp) { break; } } }

Our first task is to check the color of sibling of our parent, for simplicity lets call it as aunt . Lets assume that aunt is RED, with the following tree looks like,

... | gp:B / \ parent:R aunt:R / new:R

Since the tree broke the second rule, we fix it by making the grand-parent RED and parent and aunt as BLACK, so the tree would be like,

... | gp:R / \ parent:B aunt:B / new:R

Continuing from our previous loop, the code for this condition would be like these,

static TreeNode* INSERT_FIXUP(TreeNode* root, TreeNode* node) { TreeNode* parent = NULL; TreeNode* gp = NULL; // grand parent; TreeNode* auth = NULL; // this is the sibling of node's parent. parent = node->get_parent(); while (parent && parent->is_red()) { gp = node->get_grand_parent(); if (!gp) { break; } if (parent->is_left_of(gp)) { aunt = gp->right; if (aunt && aunt->is_red()) { parent->set_black(); auth->set_black(); gp->set_red(); node = gp; } } else { ... } } }

What if aunt have childs? Would that make the three unbalanced? The answer is the RED aunt will never have childs. Remember, when we insert node to the tree, the node is at the bottom, which means its parent and/or aunt is at the bottom too. Even if the aunt is BLACK, the tree would be unbalance from the start because parent is RED, unless they have BLACK childs.

Our next condition is if aunt is BLACK and new node is the right child or parent, with the following illustration,

... | gp:B / \ parent:R aunt:B \ new:R

To fix the tree we rotate the parent to the left, set node to start again from bottom (node = parent), make the node's parent into BLACK, make the grand-parent into RED, and then rotate the grand-parent to the right.

... ... | => | gp:R new:B / \ / \ new:B aunt:B parent:R gp:R / \ parent:R aunt:B

The code for this condition would be like,

static TreeNode* INSERT_FIXUP(TreeNode* root, TreeNode* node) { TreeNode* parent = NULL; TreeNode* gp = NULL; // grand parent; TreeNode* auth = NULL; // this is the sibling of node's parent. parent = node->get_parent(); while (parent && parent->is_red()) { gp = node->get_grand_parent(); if (!gp) { break; } if (parent->is_left_of(gp)) { aunt = gp->right; if (aunt && aunt->is_red()) { parent->set_black(); auth->set_black(); gp->set_red(); node = gp; } else { if (node->is_right_of(parent)) { RBT.root = tree_rotate_left(RBT.root, parent); node = parent; } node->parent->set_black(); gp->set_red(); RBT.root = tree_rotate_right(RBT.root, gp); } } else { ... } } }