public bool IsRed(RBNode <T> node) { if (node == null) { return(false); } return(node.isRed); }
public void Insert(T value) { RBNode <T> node = new RBNode <T>(value); head = InsertHelper(node, head); head.isRed = false; Count++; }
private RBNode <T> RightRotation(RBNode <T> node) { RBNode <T> temp = node.left; node.left = temp.right; temp.right = node; temp.isRed = node.isRed; temp.right.isRed = true; return(temp); }
private RBNode <T> MoveRedRight(RBNode <T> node) { FlipColor(node); if (IsRed(node.left.left)) { node = RightRotation(node); FlipColor(node); } return(node); }
/// <summary> /// Finds the greatest child of the node given. /// </summary> /// <returns>The greatest child.</returns> /// <param name="me">The node that is to be searched. WHEN USING IN DELETE, MAKE SURE TO CALL THIS ON node.left NOT node.</param> RBNode <T> FindRightestChild(RBNode <T> me) { if (me.right is RBNullNode <T> ) { return(me); } else { return(FindRightestChild(me.right)); } }
public void AddWithNode(RBValNode <T> newItem) { if (topNode == null) { topNode = newItem; newItem.left = new RBNullNode <T>(); InsertCheck(newItem); return; } AddLoop(newItem, topNode); }
public void PostOrder(RBNode <T> node) { if (node.left != null) { PostOrder(node.left); } if (node.right != null) { PostOrder(node.right); } Console.WriteLine(node.item); }
private void PreOrder(RBNode <T> node) { Console.WriteLine(node.item); if (node.left != null) { PreOrder(node.left); } if (node.right != null) { PreOrder(node.right); } }
/// <summary> /// Removes a value from the tree /// </summary> /// <param name="value">value to be removed</param> /// <param name="search"></param> /// <returns>the new root of the operation</returns> private RBNode <T> RemoveHelper(T value, RBNode <T> search) { if (search == null) { return(null); } if (value.CompareTo(search.item) < 0 && search.left != null) //moving left { if (!IsRed(search.left) && !IsRed(search.left.left)) //check if left node is 2 node { search = MoveRedLeft(search); } search.left = RemoveHelper(value, search.left); } else //moving right { if (IsRed(search.left)) { search = RightRotation(search); } //found leaf value else if (value.CompareTo(search.item) == 0 && search.right == null) { return(null); } //if the value is found as an internal node else if (value.CompareTo(search.item) == 0 && (search.left != null || search.right != null)) //copy the candidate value into the current node //recursivly delete the candidate value that was lower in the tree { if (!IsRed(search.right) && !IsRed(search.right.left)) { search = MoveRedRight(search); } RBNode <T> candidate = search.right; while (candidate.left != null) { candidate = candidate.left; //bug here i think } search.item = candidate.item; search.right = RemoveHelper(candidate.item, search.right); } //if our right node is a 2 node, MoveRedRight else if (!IsRed(search.right) && search.right != null && !IsRed(search.right.left)) { search = MoveRedRight(search); } //continue right search.right = RemoveHelper(value, search.right); } //fixup return(FixUp(search)); }
private RBNode <T> LeanLeft(RBNode <T> node) { if (IsRed(node.right)) { node = LeftRotation(node); } if (IsRed(node.left) && IsRed(node.left.left)) { node = RightRotation(node); } return(node); }
private RBNode <T> FixUp(RBNode <T> node) { node = LeanLeft(node); if (IsRed(node.left) && IsRed(node.right)) { FlipColor(node); } if (node.left != null && !IsRed(node.left.left) && IsRed(node.left.right)) { node = LeanLeft(node.left); } return(node); }
public RBValNode(T val, RBNode <T> leftNode = null, RBNode <T> rightNode = null, RBNode <T> parent = null) { base.val = val; left = leftNode; if (leftNode == null) { left = new RBNullNode <T>(); } right = rightNode; if (rightNode == null) { right = new RBNullNode <T>(); } this.parent = parent; }
private RBNode <T> MoveRedLeft(RBNode <T> node) { FlipColor(node); if (IsRed(node.right.left)) { node.right = RightRotation(node.right); node = LeftRotation(node); } FlipColor(node); if (IsRed(node.right.right)) { node.right = LeftRotation(node.right); } return(node); }
/// <summary> /// Checks after deletion. /// </summary> /// <param name="u">The old node that got deleted</param> /// <param name="v">Te new node that replaced the old node. This can be a nil node</param> void DeleteCheck(RBNode <T> u, RBNode <T> v) { //v is node to be deleted, u is the one that replaces it if (u.color == Enums.Colors.red || v.color == Enums.Colors.red) { u.color = Enums.Colors.black; } else { //if both u and v are black if (u == topNode) { u.color = Enums.Colors.black; } else { FixDoubleBlack(u); } } }
RBNode <T> FindNodeWithValueHelper(T val, RBNode <T> me) { if (me is RBNullNode <T> ) { throw new Exception("Could not find node."); } int comparison = me.val.CompareTo(val); if (comparison > 0) { return(FindNodeWithValueHelper(val, me.left)); } else if (comparison < 0) { return(FindNodeWithValueHelper(val, me.right)); } else { return(me); } }
void InsertCheck(RBNode <T> me) { if (me != topNode && me.parent.color != Enums.Colors.black) //If x is root, change color to BLACK { //Do the following if x's parent is not Black AND x is not root RBNode <T> uncle = (me.parent.parent.left == me.parent) ? me.parent.parent.right : me.parent.parent.left; if (uncle.color == Enums.Colors.red) { //if x's uncle is red me.parent.color = Enums.Colors.black; //change color of parent to black uncle.color = Enums.Colors.black; //change color of uncle to black me.parent.parent.color = Enums.Colors.red; //make grandparent red InsertCheck(me.parent.parent); //rule check my grandparent } else { //if x's uncle is black (OR NULLNODE: Nullnodes are black!) if (me.parent.right == me) { //if i'm a right child if (me.parent.parent.right == me.parent) { //right-right case RotateNodeLeft(me.parent.parent); //rotate grandparent left //and swap grandparent and parent colors var swapColor = me.parent.left.color; me.parent.left.color = me.parent.color; me.parent.color = swapColor; } else if (me.parent.parent.left == me.parent) { //left-right case RotateNodeLeft(me.parent); RotateNodeRight(me.parent); //rotate grandparent right //and swap grandparent and parent colors var swapColor = me.right.color; me.right.color = me.color; me.color = swapColor; } else { throw new Exception("AAH! My grandparent disowned my parent!"); } } else if (me.parent.left == me) { //if i'm a left child if (me.parent.parent.right == me.parent) { //right-left case RotateNodeRight(me.parent); RotateNodeLeft(me.parent); //rotate grandparent left //and swap grandparent and parent colors (REWORDED: MY PARENT AND SIBILING) var swapColor = me.left.color; me.left.color = me.color; me.color = swapColor; } else if (me.parent.parent.left == me.parent) { //left-left case RotateNodeRight(me.parent.parent); //rotate grandparent right //and swap grandparent and parent colors var swapColor = me.parent.right.color; me.parent.right.color = me.parent.color; me.parent.color = swapColor; } else { throw new Exception("AAH! My grandparent disowned my parent!"); } } else { throw new Exception("AAH! The parents disowned the added node!"); } } } topNode.color = Enums.Colors.black; }
void FixDoubleBlack(RBNode <T> doubleBlackNode) { RBNode <T> sibling; bool isSiblingLeft; if (doubleBlackNode.parent.left == doubleBlackNode) { sibling = doubleBlackNode.parent.right; isSiblingLeft = false; } else if (doubleBlackNode.parent.right == doubleBlackNode) { sibling = doubleBlackNode.parent.left; isSiblingLeft = true; } else { throw new Exception("doubleBlackNode is not one of its parent's children!"); } if (sibling.color == Enums.Colors.red) { //if sibling is red RBNode <T> oldParent = doubleBlackNode.parent; if (isSiblingLeft) //move sibling up { RotateNodeRight(doubleBlackNode.parent); } else { RotateNodeLeft(doubleBlackNode.parent); } if (oldParent.color == Enums.Colors.red) { //recolor old parent oldParent.color = Enums.Colors.black; } else { oldParent.color = Enums.Colors.red; } if (sibling.color == Enums.Colors.red) { //recolor old sibling. sibling.color = Enums.Colors.black; } else { sibling.color = Enums.Colors.red; } FixDoubleBlack(doubleBlackNode); //do it again, with the rotated tree } else if (sibling.left.color == Enums.Colors.red || sibling.right.color == Enums.Colors.red) { //if sibling has a red child if (sibling.left.color == Enums.Colors.red) { //if sibling's red child is left child if (sibling.parent.left == sibling) { //and sibling is a left child //LEFT LEFT CASE RotateNodeRight(sibling.parent); var swap = sibling.parent.color; sibling.parent.color = sibling.color; sibling.color = swap; } else { //and sibling is a right child //RIGHT LEFT CASE RotateNodeRight(sibling); //and do right right case RotateNodeLeft(sibling.parent); var swap = sibling.parent.color; sibling.parent.color = sibling.color; sibling.color = swap; } } else { //if sibling's red child is right child if (sibling.parent.left == sibling) { //and sibling is a left child //LEFT RIGHT CASE RotateNodeLeft(sibling); //and do left left case RotateNodeRight(sibling.parent); var swap = sibling.parent.color; sibling.parent.color = sibling.color; sibling.color = swap; } else { //and sibling is a right child //RIGHT RIGHT CASE RotateNodeLeft(sibling.parent); var swap = sibling.parent.color; sibling.parent.color = sibling.color; sibling.color = swap; } } } else { //if sibling is black and has no red children sibling.color = Enums.Colors.red; if (doubleBlackNode.parent.color == Enums.Colors.red) { doubleBlackNode.parent.color = Enums.Colors.black; } else { FixDoubleBlack(doubleBlackNode.parent); } } }
public void FlipColor(RBNode <T> node) { node.left.isRed = !node.left.isRed; node.isRed = !node.isRed; node.right.isRed = !node.right.isRed; }
public void Remove(T value) { head = RemoveHelper(value, head); Count--; }
public RBTree(T firstNodeVal) { topNode = new RBValNode <T>(firstNodeVal); }
public void Delete(RBNode <T> nodeToDelete) { //Do a BST delete. If Delete() is called on another node (in a special case) then the check is CANCELED on the original "deleted" node. if (nodeToDelete.left is RBNullNode <T> && nodeToDelete.right is RBNullNode <T> ) { //no children RBNode <T> oldNode = nodeToDelete; RBNode <T> newNode = new RBNullNode <T>(); DeleteCheck(oldNode, newNode); if (nodeToDelete == topNode) //roundabout way to say nodeToDelete = newNode. But that doesn't work because of refs { topNode = newNode; topNode.parent = null; } else if (nodeToDelete.parent.left == nodeToDelete) { nodeToDelete.parent.left = newNode; } else if (nodeToDelete.parent.right == nodeToDelete) { nodeToDelete.parent.right = newNode; } else { throw new Exception("Some kind of parenting issue"); } } else if (nodeToDelete.right is RBNullNode <T> ) { //the only child is left RBNode <T> oldNode = nodeToDelete; RBNode <T> newNode = nodeToDelete.left; DeleteCheck(oldNode, newNode); if (nodeToDelete == topNode) { //roundabout way to say nodeToDelete = newNode. But that doesn't work because of refs topNode = newNode; } else if (nodeToDelete.parent.left == nodeToDelete) { nodeToDelete.parent.left = newNode; } else if (nodeToDelete.parent.right == nodeToDelete) { nodeToDelete.parent.right = newNode; } else { throw new Exception("Some kind of parenting issue"); } } else if (nodeToDelete.left is RBNullNode <T> ) { //only child is right RBNode <T> oldNode = nodeToDelete; RBNode <T> newNode = nodeToDelete.right; DeleteCheck(oldNode, newNode); if (nodeToDelete == topNode) { //roundabout way to say nodeToDelete = newNode. But that doesn't work because of refs topNode = newNode; } else if (nodeToDelete.parent.left == nodeToDelete) { nodeToDelete.parent.left = newNode; } else if (nodeToDelete.parent.right == nodeToDelete) { nodeToDelete.parent.right = newNode; } else { throw new Exception("Some kind of parenting issue"); } } else { RBNode <T> replacer = FindRightestChild(nodeToDelete.left); nodeToDelete.val = replacer.val; Delete(replacer); } }
public RBTree() { topNode = null; }