private void RebalancePostInsertion(RBTreeNode newNode) { /** * Insert function places newNode as an appropriate leaf for a regular BST but * not necessarily a Red-black tree. Check if newNode's parent is RED (ie. if it * breaks a only red-black tree condition). If so, use the RED and BLACK labels * of newNode's parent, grandparent, and/or pibling (aunt/uncle) to balance. * * Note on conceptualizing this process: * At this point, newNode is a RED leaf whose addition may cause the tree to * not meet the required RED-BLACK conditions (noted in class description) * such that it is imbalanced beyond the red-black tree threshold. In order * to correct for this, we re-balance and/or recolor the subtree rooted at * newNode's grandparent. We perform this process iteratively, reassigning * newNode to its decendants (parents/grandparents), until we reach the root. * At no point do we consider ancestors of newNode. * * See this page for a more detailed overview of the process: * https://www.geeksforgeeks.org/red-black-tree-set-2-insert/ */ if (newNode.GrandParent() == null) { return; } RBTreeNode u; // Will represent pibling (aunt/uncle) or parent of newNode. // ie. given newNode's grandparent (gP), u can be either gP's // left or right child while (newNode.Parent().IsRed()) { // Case: p is the RIGHT child of gP: if (newNode.Parent() == newNode.GrandParent().Right()) { // Set u as the (LEFT) pibling of newNode u = newNode.GrandParent().Left(); // Case: u exists and is RED: set both u & p to BLACK, set gP to RED, // assign newNode = gP if (u != null && u.IsRed()) { u.SetBlack(); newNode.Parent().SetBlack(); newNode.GrandParent().SetRed(); newNode = newNode.GrandParent(); } else // Case: the (LEFT) pibling of newNode is BLACK // Case: newNode is the left child of p: assign newNode = p and // right rotate newNode { if (newNode == newNode.Parent().Left()) { newNode = newNode.Parent(); RotateRight(newNode); } // Set p to BLACK and gP to RED. Then left rotate gP. newNode.Parent().SetBlack(); newNode.GrandParent().SetRed(); RotateLeft(newNode.GrandParent()); } } else // Case: p is the LEFT child of gP: // Assign u as the (RIGHT) pibling of newNode { u = newNode.GrandParent().Right(); // Case: u is RED: set the color of both children of gP to BLACK, set // gp to RED. Assign gP = newNode. if (u != null && u.IsRed()) { u.SetBlack(); newNode.Parent().SetBlack(); newNode.GrandParent().SetRed(); newNode = newNode.GrandParent(); } else { // Case: newNode is the right child of p then: set p = newNode. // Then left rotate newNode. if (newNode == newNode.Parent().Right()) { newNode = newNode.Parent(); RotateLeft(newNode); } // Set color of p as BLACK and color of gP as RED. Then right // rotate gP. newNode.Parent().SetBlack(); newNode.GrandParent().SetRed(); RotateRight(newNode.GrandParent()); } } if (newNode == Root) { break; } } Root.SetBlack(); }
public RBTreeNode GrandParent() { return(ParentNode.Parent()); }
private void RebalancePostDeletion(RBTreeNode node) { // Very similar to RebalancePostInsertion function // node is the node in the location of/closest to the node just deleted RBTreeNode s; // represents sibbling of node while (node != Root && node.IsBlack()) { if (node == node.Parent().Left()) { s = node.Parent().Right(); if (s.IsRed()) // case 1 { s.SetBlack(); node.Parent().SetRed(); RotateLeft(node.Parent()); s = node.Parent().Right(); } if (s.Left().IsBlack() && s.Right().IsBlack()) // case 2 { s.SetRed(); node = node.Parent(); } else { if (s.Right().IsBlack()) // case 3 { s.Left().SetBlack(); s.SetRed(); RotateRight(s); s = node.Parent().Right(); } if (s.Parent().IsRed()) { s.SetRed(); } else { s.SetBlack(); } node.Parent().SetBlack(); s.Right().SetBlack(); RotateLeft(s.Parent()); node = Root; } } else { s = node.Parent().Left(); if (s.IsRed()) { s.SetBlack(); node.Parent().SetRed(); RotateRight(node.Parent()); s = node.Parent().Left(); } if (s.Right() == null) { s.SetRight(Leaf); } if (s.Left() == null) { s.SetLeft(Leaf); } if (s.Right().IsBlack() && s.Left().IsBlack()) { s.SetRed(); node = node.Parent(); } else { if (s.Left().IsBlack()) { s.Right().SetBlack(); s.SetRed(); RotateLeft(s); s = node.Parent().Left(); } if (s.Parent().IsRed()) { s.SetRed(); } else { s.SetBlack(); } node.Parent().SetBlack(); s.Left().SetBlack(); RotateRight(node.Parent()); node = Root; } } } node.SetBlack(); }