/// <summary> /// Ensures the tree follows red-black properties after an insertion of the given node. /// </summary> private void InsertRepair(PointerBackedBinaryTreeNode <RedBlackTreeNode <T> > currentNode) { if (currentNode.Parent == null) { // If this is the root node, it must be black. It will currently be red, because // that is the color new nodes are added as. currentNode.Data.IsBlack = true; } else if (currentNode.Parent.Data.IsBlack) { // If the parent node is black, the red-black ordering isn't invalidated, so do nothing. } else if (currentNode.GetUncle()?.Data.IsBlack == false) { // There is a red uncle (and the current node is red), so we can switch then both to black with the // grandparent becoming red. This may violate #2, so we need to rerun the recursion. currentNode.Parent.Data.IsBlack = true; currentNode.GetUncle().Data.IsBlack = true; // Because we found an uncle, a grandparent is guaranteed to exist. currentNode.Parent.Parent.Data.IsBlack = false; InsertRepair(currentNode.Parent.Parent); } else // parent is red, uncle is black or missing, grandparent definitely exists. { // Rotate left or right and then reverse the rotation later to effectively switch nodes around // and satisfy red-black height and color properties if (currentNode == currentNode.Parent.Right && currentNode.Parent == currentNode.Parent.Parent.Left) { this.RotateLeft(currentNode.Parent); currentNode = currentNode.Left; currentNode.Parent.Data.IsBlack = true; currentNode.Parent.Parent.Data.IsBlack = false; this.RotateRight(currentNode.Parent.Parent); } else if (currentNode == currentNode.Parent.Left && currentNode.Parent == currentNode.Parent.Parent.Right) { this.RotateRight(currentNode.Parent); currentNode = currentNode.Right; currentNode.Parent.Data.IsBlack = true; currentNode.Parent.Parent.Data.IsBlack = false; this.RotateLeft(currentNode.Parent.Parent); } } }
public void GetUncleFindsNoUncleWhenNoneExists() { PointerBackedBinaryTreeNode <string> testNode = new PointerBackedBinaryTreeNode <string>("abc", null); Assert.IsNull(testNode.GetUncle()); testNode.Left = new PointerBackedBinaryTreeNode <string>("def", testNode); testNode.Left.Left = new PointerBackedBinaryTreeNode <string>("geh", testNode.Left); Assert.IsNull(testNode.Left.GetUncle()); Assert.IsNull(testNode.Left.Left.GetUncle()); }