///<summary> /// GetMaxKey /// Returns the maximum key value ///</summary> public TKey GetMaxKey() { var work_node = _tree_base_node; if (work_node == null || work_node == RedBlackNode <TKey, TValue> .SentinelNode) { throw new RedBlackException(Properties.Resources.ExceptionTreeIsEmpty); } // traverse to the extreme right to find the largest key while (work_node.Right != RedBlackNode <TKey, TValue> .SentinelNode) { work_node = work_node.Right; } _last_node_found = work_node; return(work_node.Key); }
///<summary> /// Balance Tree After Insert /// Additions to red-black trees usually destroy the red-black /// properties. Examine the tree and restore. Rotations are normally /// required to restore it ///</summary> private void BalanceTreeAfterInsert(RedBlackNode <TKey, TValue> inserted_node) { // x and y are used as variable names for brevity, in a more formal // implementation, you should probably change the names // maintain red-black tree properties after adding newNode while (inserted_node != _tree_base_node && inserted_node.Parent.Color == RedBlackNodeType.Red) { // Parent node is .Colored red; RedBlackNode <TKey, TValue> work_node; if (inserted_node.Parent == inserted_node.Parent.Parent.Left) // determine traversal path { // is it on the Left or Right subtree? work_node = inserted_node.Parent.Parent.Right; // get uncle if (work_node != null && work_node.Color == RedBlackNodeType.Red) { // uncle is red; change x's Parent and uncle to black inserted_node.Parent.Color = RedBlackNodeType.Black; work_node.Color = RedBlackNodeType.Black; // grandparent must be red. Why? Every red node that is not // a leaf has only black children inserted_node.Parent.Parent.Color = RedBlackNodeType.Red; inserted_node = inserted_node.Parent.Parent; // continue loop with grandparent } else { // uncle is black; determine if newNode is greater than Parent if (inserted_node == inserted_node.Parent.Right) { // yes, newNode is greater than Parent; rotate Left // make newNode a Left child inserted_node = inserted_node.Parent; RotateLeft(inserted_node); } // no, newNode is less than Parent inserted_node.Parent.Color = RedBlackNodeType.Black; // make Parent black inserted_node.Parent.Parent.Color = RedBlackNodeType.Red; // make grandparent black RotateRight(inserted_node.Parent.Parent); // rotate right } } else { // newNode's Parent is on the Right subtree // this code is the same as above with "Left" and "Right" swapped work_node = inserted_node.Parent.Parent.Left; if (work_node != null && work_node.Color == RedBlackNodeType.Red) { inserted_node.Parent.Color = RedBlackNodeType.Black; work_node.Color = RedBlackNodeType.Black; inserted_node.Parent.Parent.Color = RedBlackNodeType.Red; inserted_node = inserted_node.Parent.Parent; } else { if (inserted_node == inserted_node.Parent.Left) { inserted_node = inserted_node.Parent; RotateRight(inserted_node); } inserted_node.Parent.Color = RedBlackNodeType.Black; inserted_node.Parent.Parent.Color = RedBlackNodeType.Red; RotateLeft(inserted_node.Parent.Parent); } } } _tree_base_node.Color = RedBlackNodeType.Black; // rbTree should always be black }
///<summary> /// BalanceTreeAfterDelete /// Deletions from red-black trees may destroy the red-black /// properties. Examine the tree and restore. Rotations are normally /// required to restore it ///</summary> private void BalanceTreeAfterDelete(RedBlackNode <TKey, TValue> linked_node) { // maintain Red-Black tree balance after deleting node while (linked_node != _tree_base_node && linked_node.Color == RedBlackNodeType.Black) { RedBlackNode <TKey, TValue> work_node; // determine sub tree from parent if (linked_node == linked_node.Parent.Left) { // y is x's sibling work_node = linked_node.Parent.Right; if (work_node.Color == RedBlackNodeType.Red) { // x is black, y is red - make both black and rotate linked_node.Parent.Color = RedBlackNodeType.Red; work_node.Color = RedBlackNodeType.Black; RotateLeft(linked_node.Parent); work_node = linked_node.Parent.Right; } if (work_node.Left.Color == RedBlackNodeType.Black && work_node.Right.Color == RedBlackNodeType.Black) { // children are both black // change parent to red work_node.Color = RedBlackNodeType.Red; // move up the tree linked_node = linked_node.Parent; } else { if (work_node.Right.Color == RedBlackNodeType.Black) { work_node.Left.Color = RedBlackNodeType.Black; work_node.Color = RedBlackNodeType.Red; RotateRight(work_node); work_node = linked_node.Parent.Right; } linked_node.Parent.Color = RedBlackNodeType.Black; work_node.Color = linked_node.Parent.Color; work_node.Right.Color = RedBlackNodeType.Black; RotateLeft(linked_node.Parent); linked_node = _tree_base_node; } } else { // right subtree - same as code above with right and left swapped work_node = linked_node.Parent.Left; if (work_node.Color == RedBlackNodeType.Red) { linked_node.Parent.Color = RedBlackNodeType.Red; work_node.Color = RedBlackNodeType.Black; RotateRight(linked_node.Parent); work_node = linked_node.Parent.Left; } if (work_node.Right.Color == RedBlackNodeType.Black && work_node.Left.Color == RedBlackNodeType.Black) { work_node.Color = RedBlackNodeType.Red; linked_node = linked_node.Parent; } else { if (work_node.Left.Color == RedBlackNodeType.Black) { work_node.Right.Color = RedBlackNodeType.Black; work_node.Color = RedBlackNodeType.Red; RotateLeft(work_node); work_node = linked_node.Parent.Left; } work_node.Color = linked_node.Parent.Color; linked_node.Parent.Color = RedBlackNodeType.Black; work_node.Left.Color = RedBlackNodeType.Black; RotateRight(linked_node.Parent); linked_node = _tree_base_node; } } } linked_node.Color = RedBlackNodeType.Black; }
///<summary> /// Delete /// Delete a node from the tree and restore red black properties ///</summary> private void Delete(RedBlackNode <TKey, TValue> delete_node) { // A node to be deleted will be: // 1. a leaf with no children // 2. have one child // 3. have two children // If the deleted node is red, the red black properties still hold. // If the deleted node is black, the tree needs rebalancing // work node RedBlackNode <TKey, TValue> work_node; // find the replacement node (the successor to x) - the node one with // at *most* one child. if (delete_node.Left == RedBlackNode <TKey, TValue> .SentinelNode || delete_node.Right == RedBlackNode <TKey, TValue> .SentinelNode) { // node has sentinel as a child work_node = delete_node; } else { // z has two children, find replacement node which will // be the leftmost node greater than z // traverse right subtree work_node = delete_node.Right; // to find next node in sequence while (work_node.Left != RedBlackNode <TKey, TValue> .SentinelNode) { work_node = work_node.Left; } } // at this point, y contains the replacement node. it's content will be copied // to the valules in the node to be deleted // x (y's only child) is the node that will be linked to y's old parent. var linked_node = work_node.Left != RedBlackNode <TKey, TValue> .SentinelNode ? work_node.Left : work_node.Right; // replace x's parent with y's parent and // link x to proper subtree in parent // this removes y from the chain linked_node.Parent = work_node.Parent; if (work_node.Parent != null) { if (work_node == work_node.Parent.Left) { work_node.Parent.Left = linked_node; } else { work_node.Parent.Right = linked_node; } } else { // make x the root node _tree_base_node = linked_node; } // copy the values from y (the replacement node) to the node being deleted. // note: this effectively deletes the node. if (work_node != delete_node) { delete_node.Key = work_node.Key; delete_node.Data = work_node.Data; } if (work_node.Color == RedBlackNodeType.Black) { BalanceTreeAfterDelete(linked_node); } _last_node_found = RedBlackNode <TKey, TValue> .SentinelNode; Interlocked.Decrement(ref _count); InvokeOnRemove(new RedBlackEventArgs <TKey, TValue> { Item = delete_node.Data, Key = delete_node.Key }); }
///<summary> /// Clear /// Empties or clears the tree ///</summary> public void Clear() { _tree_base_node = RedBlackNode <TKey, TValue> .SentinelNode; _count = 0; InvokeOnClear(new EventArgs()); }