private void RemoveNode(IntervalNode <TKey, TValue> node) { if (node == Sentinel) { return; } IntervalNode <TKey, TValue> temp = node; if (node.Right != Sentinel && node.Left != Sentinel) { // Trick when deleting node with both children, switch it with closest in order node // swap values and delete the bottom node converting it to other cases temp = node.GetSuccessor(); node.Interval = temp.Interval; node.RecalculateMaxEnd(); while (node.Parent != Sentinel) { node = node.Parent; node.RecalculateMaxEnd(); } } node = temp; temp = node.Left != Sentinel ? node.Left : node.Right; // we will replace node with temp and delete node temp.Parent = node.Parent; if (node.IsRoot) { Root = temp; // Set new root } else { // Reattach node to parent if (node.ParentDirection == NodeDirection.RIGHT) { node.Parent.Left = temp; } else { node.Parent.Right = temp; } IntervalNode <TKey, TValue> maxAux = node.Parent; maxAux.RecalculateMaxEnd(); while (maxAux.Parent != Sentinel) { maxAux = maxAux.Parent; maxAux.RecalculateMaxEnd(); } } if (node.Color == NodeColor.BLACK) { RenewConstraintsAfterDelete(temp); } }
/// <summary> /// General left rotation /// </summary> /// <param name="node">top of rotated subtree</param> private void RotateLeft(IntervalNode <TKey, TValue> node) { var pivot = node.Right; NodeDirection dir = node.ParentDirection; var parent = node.Parent; var tempTree = pivot.Left; pivot.Left = node; node.Parent = pivot; node.Right = tempTree; if (tempTree != Sentinel) { tempTree.Parent = node; } if (dir == NodeDirection.LEFT) { parent.Right = pivot; } else if (dir == NodeDirection.RIGHT) { parent.Left = pivot; } else { Root = pivot; } pivot.Parent = parent; pivot.RecalculateMaxEnd(); node.RecalculateMaxEnd(); }