public void Delete(RBTreeNode node, int value) { // Traverse until we find nodeToDelete RBTreeNode nodeToDelete = null; while (node != null) { if (node.GetData() == value) { nodeToDelete = node; break; } node = (value < node.GetData()) ? node.Left() : node.Right(); } if (nodeToDelete == null) { throw new Exception("Cannot find node to delete with " + $"value {value} in Red Black Tree"); } RBTreeNode x, y; // Save the color of nodeToDelete bool originallyRed = nodeToDelete.IsRed(); // If nodeToDelete only has left children, replace with its left subtree if (nodeToDelete.Left() == null || nodeToDelete.Left().IsEmpty()) { x = nodeToDelete.Right(); if (x == null) { x = Leaf; } Transplant(nodeToDelete, x); // If nodeToDelete only has right children, replace with its right subtree } else if (nodeToDelete.Right() == null || nodeToDelete.Right().IsEmpty()) { x = nodeToDelete.Left(); if (x == null) { x = Leaf; } Transplant(nodeToDelete, x); } else // nodeToDelete either has two children or is a leaf // y = smallest node whose value is greater than that of nodeToDelete // will replace nodeToDelete { y = Minimum(nodeToDelete.Right()); originallyRed = y.IsRed(); // x = subtree root with values greater than y x = y.Right(); if (x == null) { x = Leaf; } // if y is a child of nodeToDelete, x is already stored in the right place if (y.Parent() == nodeToDelete) { x.SetParent(y); } else // else replace y with its right subtree and update attributes { Transplant(y, y.Right()); y.SetRight(nodeToDelete.Right()); y.Right().SetParent(y); } // replace nodeToDelete with y and update attributes Transplant(nodeToDelete, y); y.SetLeft(nodeToDelete.Left()); y.Left().SetParent(y); // y will replace nodeToDelete's location in tree, update its color if (originallyRed) { y.SetRed(); } else { y.SetBlack(); } } if (!(originallyRed)) { RebalancePostDeletion(x); } }