// returns -# for failure, or number of blacks to leaves public virtual int TestIntegrityNode(RedBlackNode <KeyType, DataType> node) { if (node == null) { return(1); } if (node.Left != null) { if (node.Left.Parent != node) { return(-1); } if (node.Left.Key.CompareTo(node.Key) > 0) { return(-3); } } if (node.Right != null) { if (node.Right.Parent != node) { return(-2); } if (node.Right.Key.CompareTo(node.Key) < 0) { return(-4); } } if (node.Color == RED && ((node.Left != null && node.Left.Color == RED) || (node.Right != null && node.Right.Color == RED))) { return(-5); } // Recurse! Count the number of blacks below us int leftCount = TestIntegrityNode(node.Left); int rightCount = TestIntegrityNode(node.Right); if (leftCount != rightCount) { return(-6); } return(leftCount + (node.Color == BLACK ? 1 : 0)); }
/***** Remove Operation *****/ ///<summary> /// Remove /// removes the key and data object (delete) ///<summary> public virtual bool Remove(KeyType key) { if (key == null) { throw(new ArgumentNullException()); } // find node RedBlackNode <KeyType, DataType> node = Search(key); if (node == null) { return(false); // not found! } Delete(node); return(true); }
// We may have multiple, so check against object public virtual bool Remove(KeyType key, DataType obj) { if (obj == null) { throw (new RedBlackException("RedBlackNode object is null")); } // find node RedBlackNode <KeyType, DataType> node = Search(key, obj); if (node == null) { // not found! return(false); } Delete(node); return(true); }
// don't call remove-- derived classes will remove! public virtual void ChangeSalience(DataType obj, double before, double after) { if (obj == null) { throw (new RedBlackException("ChangeSalience object is null")); } // find node RedBlackNode <double, DataType> node = Search(before, obj); if (node == null) { throw (new RedBlackException("ChangeSalience object not found")); } Delete(node); Add(after, obj); }
///<summary> /// GetMaxKey /// Returns the maximum key value ///<summary> public KeyType GetMaxKey() { RedBlackNode <KeyType, DataType> treeNode = rbTree; if (treeNode == null) { throw (new RedBlackException("RedBlack tree is empty")); } // traverse to the extreme right to find the largest key while (treeNode.Right != null) { treeNode = treeNode.Right; } lastNodeFound = treeNode; return(treeNode.Key); }
///<summary> /// RotateRight /// Rebalance the tree by rotating the nodes to the right ///</summary> public void RotateRight(RedBlackNode <KeyType, DataType> x) { // pushing node x down and to the Right to balance the tree. x's Left child (y) // replaces x (since x < y), and y's Right child becomes x's Left child // (since it's < x but > y). RedBlackNode <KeyType, DataType> y = x.Left; // get x's Left node, this becomes y // set x's Right link x.Left = y.Right; // y's Right child becomes x's Left child // modify parents if (y.Right != null) { y.Right.Parent = x; // sets y's Right Parent to x } if (y != null) { y.Parent = x.Parent; // set y's Parent to x's Parent } if (x.Parent != null) // null=rbTree, could also have used rbTree { // determine which side of it's Parent x was on if (x == x.Parent.Right) { x.Parent.Right = y; // set Right Parent to y } else { x.Parent.Left = y; // set Left Parent to y } } else { rbTree = y; // at rbTree, set it to y } // link x and y y.Right = x; // put x on y's Right if (x != null) // set y as x's Parent { x.Parent = y; } }
public override void Deserialize(SerializationReader reader) { salienceSum = reader.ReadDouble(); // salienceSum = info.GetDouble("salienceSum"); // : base(info, ctxt) intCount = reader.ReadInt32(); if (intCount != 0) { RedBlackNode <double, DataType>[] containers = new RedBlackNode <double, DataType> [intCount]; int ii = 0; rbTree = DeserializeTree(reader, containers, ref ii); for (int jj = 0; jj < intCount; jj++) { containers[jj].Data = (DataType)reader.ReadPointer(); } } else { rbTree = null; } }
public RedBlackNode <KeyType, DataType> ContainsUnderNode(DataType obj, RedBlackNode <KeyType, DataType> node) { if (node == null) { return(null); } if (ReferenceEquals(node.Data, obj)) { return(node); } RedBlackNode <KeyType, DataType> below = ContainsUnderNode(obj, node.Left); if (below != null) { return(below); } return(ContainsUnderNode(obj, node.Right)); }
public DataType SelectSmartItem() { double position; RedBlackNode <double, DataType> result = SelectWeightedItem(smartWeight, out position); // Adjust the weight! // We expect an object at position to give the following double expected = position * 2 * (salienceSum / intCount); if (expected > result.Key) { // Smaller than we expected-- decrease weight! smartWeight = (smartWeight + .25) / 2; } else { // More even than we expected-- increase weight! smartWeight = (smartWeight + 0.5) / 2; } return(result.Data); }
public DataType SelectRandomItem(RandomSearchQuality quality) { if (quality == RandomSearchQuality.Fast) { double position; return(SelectWeightedItem(.5, out position).Data); } else { int chosen = randgen.Next(Count); RedBlackEnumerator <double, DataType> enumerator = GetNodeEnumerator(); while (enumerator.HasMoreElements()) { RedBlackNode <double, DataType> node = enumerator.NextElement(); if (chosen-- == 0) { return(node.Data); } } return(default(DataType)); } }
// Select a codelet by carefully respecting salience public DataType SelectExactItem() { double salienceToGet = randgen.NextDouble() * salienceSum; double salienceSoFar = 0; RedBlackEnumerator <double, DataType> enumerator = GetNodeEnumerator(); while (enumerator.HasMoreElements()) { RedBlackNode <double, DataType> node = enumerator.NextElement(); salienceSoFar += node.Key; if (salienceSoFar >= salienceToGet) { return(node.Data); } } // Salience calculation failure! Console.WriteLine("WARNING: Salience miscalculation! Max is " + salienceSoFar.ToString() + " not " + salienceSum.ToString()); salienceSum = salienceSoFar; // Try again! return(SelectExactItem()); }
// Initialize a sentinel node (use BLACK as color) public RedBlackNode(int color) { rbnLeft = rbnRight = rbnParent = null; intColor = color; }
public void Reset() { Color = 0; // red rbnLeft = rbnRight = rbnParent = null; // don't reset key and data-- new allocater should! }
public RedBlackNode <KeyType, DataType> SearchRecursive(KeyType key, DataType obj, RedBlackNode <KeyType, DataType> node) { if (ReferenceEquals(node.Data, obj)) { return(node); } if (node == null) { return(null); } // One side or the other (or both) ought to be the same key RedBlackNode <KeyType, DataType> found = null; if (node.Left != null) { if (key.CompareTo(node.Left.Key) == 0) { found = SearchRecursive(key, obj, node.Left); } else { // scale down the right side-- there might be more! RedBlackNode <KeyType, DataType> below = node.Left; while (below != null && key.CompareTo(below.Key) != 0) { below = below.Right; } if (below != null) { found = SearchRecursive(key, obj, below); } } } if (found == null && node.Right != null) { int rightResult = key.CompareTo(node.Right.Key); if (rightResult == 0) { found = SearchRecursive(key, obj, node.Right); } else { // scale down the left side-- there might be more! RedBlackNode <KeyType, DataType> below = node.Right; while (below != null && key.CompareTo(below.Key) != 0) { below = below.Left; } if (below != null) { found = SearchRecursive(key, obj, below); } } } return(found); }
public void SerializeTree(SerializationWriter writer, DataType[] elements, ref int ii, RedBlackNode <double, DataType> node) { if (node == null) { writer.Write(0.0); } else { writer.Write(node.Key); writer.Write(node.Color == RED); elements[ii++] = node.Data; SerializeTree(writer, elements, ref ii, node.Left); SerializeTree(writer, elements, ref ii, node.Right); } }
///<summary> /// Clear /// Empties or clears the tree ///<summary> public virtual void Clear() { rbTree = null; intCount = 0; }
///<summary> /// RestoreAfterDelete /// 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 RestoreAfterDelete(RedBlackNode <KeyType, DataType> x, RedBlackNode <KeyType, DataType> x_parent) { // maintain Red-Black tree balance after deleting node RedBlackNode <KeyType, DataType> y; while (x != rbTree && (x == null || x.Color == BLACK)) { if (x == x_parent.Left) // determine sub tree from parent { y = x_parent.Right; // y is x's sibling if (y.Color == RED) { // x is black, y is red - make both black and rotate y.Color = BLACK; x_parent.Color = RED; RotateLeft(x_parent); y = x_parent.Right; } if ((y.Left == null || y.Left.Color == BLACK) && (y.Right == null || y.Right.Color == BLACK)) { // children are both black y.Color = RED; // change parent to red x = x_parent; // move up the tree if (x != null) { x_parent = x.Parent; } else { x_parent = null; } } else { if (y.Right == null || y.Right.Color == BLACK) { if (y.Left != null) { y.Left.Color = BLACK; } y.Color = RED; RotateRight(y); y = x_parent.Right; } y.Color = x_parent.Color; x_parent.Color = BLACK; if (y.Right != null) { y.Right.Color = BLACK; } RotateLeft(x_parent); x = rbTree; x_parent = null; } } else { // right subtree - same as code above with right and left swapped y = x_parent.Left; if (y.Color == RED) { y.Color = BLACK; x_parent.Color = RED; RotateRight(x_parent); y = x_parent.Left; } if ((y.Left == null || y.Left.Color == BLACK) && (y.Right == null || y.Right.Color == BLACK)) { y.Color = RED; x = x_parent; if (x != null) { x_parent = x.Parent; } else { x_parent = null; } } else { if (y.Left == null || y.Left.Color == BLACK) { if (y.Right != null) { y.Right.Color = BLACK; } y.Color = RED; RotateLeft(y); y = x_parent.Left; } y.Color = x_parent.Color; x_parent.Color = BLACK; if (y.Left != null) { y.Left.Color = BLACK; } RotateRight(x_parent); x = rbTree; x_parent = null; } } } if (x != null) { x.Color = BLACK; } }
/***** Add Operation *****/ ///<summary> /// Add /// args: ByVal key As IComparable, ByVal data As Object /// key is object that implements IComparable interface /// performance tip: change to use use int type (such as the hashcode) ///</summary> public virtual void Add(KeyType key, DataType data) { try { if (key == null || data == null) { throw (new RedBlackException("RedBlackNode key and data must not be null")); } // traverse tree - find where node belongs int result = 0; // create new node RedBlackNode <KeyType, DataType> node = new RedBlackNode <KeyType, DataType>(); RedBlackNode <KeyType, DataType> temp = rbTree; // grab the rbTree node of the tree while (temp != null) { // find Parent node.Parent = temp; result = key.CompareTo(temp.Key); if (result == 0) { if (temp.Left == null || temp.Right == null) { break; // good enough! } } if (result > 0) { temp = temp.Right; } else { temp = temp.Left; } } // setup node node.Key = key; node.Data = data; node.Left = null; node.Right = null; // insert node into tree starting at parent's location if (node.Parent != null) { result = node.Key.CompareTo(node.Parent.Key); if (result == 0) { if (node.Parent.Right == null) { node.Parent.Right = node; } else { node.Parent.Left = node; } } else { if (result > 0) { node.Parent.Right = node; } else { node.Parent.Left = node; } } } else { rbTree = node; // first node added } RestoreAfterInsert(node); // restore red-black properities lastNodeFound = node; intCount = intCount + 1; } catch (Exception e) { Console.WriteLine("RedBlackTree::Add threw " + e.Message); } }
public RedBlackTree() { rbTree = null; lastNodeFound = null; }
public RedBlackNode <double, DataType> SelectWeightedItem(double weight, out double position) { if (IsEmpty()) { position = .5; return(null); } double selector = randgen.NextDouble(); // Otherwise, we have a proper tree! double left = 0; // left possible-position double right = 1; // right possible-position RedBlackNode <double, DataType> node = rbTree; // current node double expectBelow = salienceSum; // total salience below node // Scale down tree while (node.Left != null && node.Right != null) { // should we take this node? double fraction = node.Key / expectBelow; if (selector < fraction) { position = (left + right) / 2; return(node); } // do we recurse on left? if (selector < fraction + weight) { node = node.Left; // update node selector -= fraction; // adjust selector from 0 to 1 selector /= weight; right = (left + right) / 2; // adjust possible range expectBelow *= weight; // change expected below } else { node = node.Right; // update node selector -= fraction + weight; // adjust salience from 0 to 1 selector /= 1 - (fraction + weight); left = (left + right) / 2; // adjust possible range expectBelow *= (1 - weight); // change expected below fraction = (weight + .5) / 2; // diff between left and write is less } } if (node.Left == null && node.Right == null) { // this is a leaf-- take it! position = (left + right) / 2; return(node); } else { // choose between these two nodes RedBlackNode <double, DataType> other = (node.Left == null ? node.Right : node.Left); double nodesSum = node.Key + other.Key; if (selector * nodesSum < node.Key) { position = (2 * left + right) / 3; return(node); } else { position = (left + 2 * right) / 3; return(other); } } }
///<summary> /// NextNode ///</summary> public RedBlackNode <KeyType, DataType> NextElement() { if (stack.Count == 0) { throw(new RedBlackException("Element not found")); } // the top of stack will always have the next item // get top of stack but don't remove it as the next nodes in sequence // may be pushed onto the top // the stack will be popped after all the nodes have been returned RedBlackNode <KeyType, DataType> node = stack.Peek(); //next node in sequence if (ascending) { if (node.Right == null) { // yes, top node is lowest node in subtree - pop node off stack RedBlackNode <KeyType, DataType> tn = stack.Pop(); // peek at right node's parent // get rid of it if it has already been used while (HasMoreElements() && stack.Peek().Right == tn) { tn = stack.Pop(); } } else { // find the next items in the sequence // traverse to left; find lowest and push onto stack RedBlackNode <KeyType, DataType> tn = node.Right; while (tn != null) { stack.Push(tn); tn = tn.Left; } } } else // descending, same comments as above apply { if (node.Left == null) { // walk the tree RedBlackNode <KeyType, DataType> tn = stack.Pop(); while (HasMoreElements() && stack.Peek().Left == tn) { tn = stack.Pop(); } } else { // determine next node in sequence // traverse to left subtree and find greatest node - push onto stack RedBlackNode <KeyType, DataType> tn = node.Left; while (tn != null) { stack.Push(tn); tn = tn.Right; } } } // the following is for .NET compatibility (see MoveNext()) Key = node.Key; Value = node.Data; return(node); }
public virtual void Deserialize(SerializationReader reader) { intCount = reader.ReadInt32(); // intCount = info.GetInt32("intCount"); rbTree = (RedBlackNode <KeyType, DataType>)reader.ReadPointer(); // rbTree = (RedBlackNode<KeyType, DataType>)info.GetValue("rbTree", typeof(RedBlackNode<KeyType, DataType>)); lastNodeFound = null; }
///<summary> /// RestoreAfterInsert /// 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 RestoreAfterInsert(RedBlackNode <KeyType, DataType> x) { // x and y are used as variable names for brevity, in a more formal // implementation, you should probably change the names RedBlackNode <KeyType, DataType> y; // maintain red-black tree properties after adding x while (x != rbTree && x.Parent.Color == RED) { // Parent node is .Colored red; if (x.Parent == x.Parent.Parent.Left) // determine traversal path { // is it on the Left or Right subtree? y = x.Parent.Parent.Right; // get uncle if (y != null && y.Color == RED) { // uncle is red; change x's Parent and uncle to black x.Parent.Color = BLACK; y.Color = BLACK; // grandparent must be red. Why? Every red node that is not // a leaf has only black children x.Parent.Parent.Color = RED; x = x.Parent.Parent; // continue loop with grandparent } else { // uncle is black; determine if x is greater than Parent if (x == x.Parent.Right) { // yes, x is greater than Parent; rotate Left // make x a Left child x = x.Parent; RotateLeft(x); } // no, x is less than Parent x.Parent.Color = BLACK; // make Parent black x.Parent.Parent.Color = RED; // make grandparent black RotateRight(x.Parent.Parent); // rotate right } } else { // x's Parent is on the Right subtree // this code is the same as above with "Left" and "Right" swapped y = x.Parent.Parent.Left; if (y != null && y.Color == RED) { x.Parent.Color = BLACK; y.Color = BLACK; x.Parent.Parent.Color = RED; x = x.Parent.Parent; } else { if (x == x.Parent.Left) { x = x.Parent; RotateRight(x); } x.Parent.Color = BLACK; x.Parent.Parent.Color = RED; RotateLeft(x.Parent.Parent); } } } if (rbTree != null) { rbTree.Color = BLACK; // rbTree should always be black } }
public DataOnly(RedBlackNode <KeyType, DataType> tnode, bool ascending) { enumerator = new RedBlackEnumerator <KeyType, DataType>(tnode, ascending); }
///<summary> /// Delete /// Delete a node from the tree and restore red black properties ///<summary> public void Delete(RedBlackNode <KeyType, DataType> z) { try { // 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 RedBlackNode <KeyType, DataType> x; // work node to contain the replacement node RedBlackNode <KeyType, DataType> y; // work node // find the replacement node (the successor to x) - the node one with // at *most* one child. if (z.Left == null || z.Right == null) { y = z; // node has sentinel as a child } else { // z has two children, find replacement node which will // be the leftmost node greater than z y = z.Right; // traverse right subtree while (y.Left != null) // to find next node in sequence { y = y.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. if (y.Left != null) { x = y.Left; } else { x = y.Right; } // replace x's parent with y's parent and // link x to proper subtree in parent // this removes y from the chain if (x != null) { x.Parent = y.Parent; } if (y.Parent != null) { if (y == y.Parent.Left) { y.Parent.Left = x; } else { y.Parent.Right = x; } } else { rbTree = x; // make x the root node } // copy the values from y (the replacement node) to the node being deleted. // note: this effectively deletes the node. if (y != z) { z.Key = y.Key; z.Data = y.Data; } if (y.Color == BLACK) { RestoreAfterDelete(x, y.Parent); } lastNodeFound = null; intCount = intCount - 1; } catch (Exception e) { Console.WriteLine("RedBlackTree::RestoreAfterDelete threw " + e.Message); } }