public RedBlackSTM() { strIdentifier = base.ToString() + rand.Next(); intHashCode = rand.Next(); // set up the sentinel node. the sentinel node is the key to a successfull // implementation and for understanding the red-black tree properties. //sentinelNode = new RedBlackSTMNode(); /* Old code*/ //sentinelNode.Left = null; //sentinelNode.Right = null; /* FIX */ sentinelNode.Left = sentinelNode; sentinelNode.Right = sentinelNode; sentinelNode.Parent = null; sentinelNode.Color = RedBlackSTMNode.BLACK; rbTree = sentinelNode; lastNodeFound = sentinelNode; }
///<summary> /// Determine order, walk the tree and push the nodes onto the stack ///</summary> public RedBlackSTMEnumerator(RedBlackSTMNode tnode, bool keys, bool ascending) { stack = new Stack(); this.keys = keys; this.ascending = ascending; // use depth-first traversal to push nodes into stack // the lowest node will be at the top of the stack if (ascending) { // find the lowest node while (tnode != RedBlackSTM.sentinelNode) { stack.Push(tnode); tnode = tnode.Left; } } else { // the highest node will be at top of stack while (tnode != RedBlackSTM.sentinelNode) { stack.Push(tnode); tnode = tnode.Right; } } }
///<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(IComparable key, RedBlackSTMNode x) { // x and y are used as variable names for brevity, in a more formal // implementation, you should probably change the names RedBlackSTMNode y; // maintain red-black tree properties after adding x while(x != rbTree && x.Parent.Color == RedBlackSTMNode.RED) { DebugPrint(key, "RestoreAfterInsert while...", x.Parent); // 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 == RedBlackSTMNode.RED) { // uncle is red; change x's Parent and uncle to black x.Parent.Color = RedBlackSTMNode.BLACK; //Console.WriteLine("x.parent.Color OK, type of Y is: {0}", y.GetType()); y.Color = 1; //Console.WriteLine("y.Color is: {0}, RedBlackSTMNode.BLACK is: {1}", y.Color, RedBlackSTMNode.BLACK); y.Color = RedBlackSTMNode.BLACK; //Console.WriteLine("y.Color OK"); // grandparent must be red. Why? Every red node that is not // a leaf has only black children x.Parent.Parent.Color = RedBlackSTMNode.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 = RedBlackSTMNode.BLACK; // make Parent black x.Parent.Parent.Color = RedBlackSTMNode.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; //DebugPrint(key, "before if...", y); if((int)key == 221) Console.WriteLine("testing if part 1 {0}", x.Parent.Parent.Left.Left); if (y != null && y.Color == RedBlackSTMNode.RED) { DebugPrint(key, "if...", y); x.Parent.Color = RedBlackSTMNode.BLACK; y.Color = RedBlackSTMNode.BLACK; x.Parent.Parent.Color = RedBlackSTMNode.RED; x = x.Parent.Parent; } else { DebugPrint(key, "else do if...", x); if (x == x.Parent.Left) { x = x.Parent; RotateRight(x); } x.Parent.Color = RedBlackSTMNode.BLACK; x.Parent.Parent.Color = RedBlackSTMNode.RED; RotateLeft(x.Parent.Parent); } } } rbTree.Color = RedBlackSTMNode.BLACK; // rbTree should always be black }
///<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(RedBlackSTMNode x) { // maintain Red-Black tree balance after deleting node RedBlackSTMNode y; while(x != rbTree && x.Color == RedBlackSTMNode.BLACK) { if (x == x.Parent.Left) // determine sub tree from parent { y = x.Parent.Right; // y is x's sibling if(y.Color == RedBlackSTMNode.RED) { // x is black, y is red - make both black and rotate y.Color = RedBlackSTMNode.BLACK; x.Parent.Color = RedBlackSTMNode.RED; RotateLeft(x.Parent); y = x.Parent.Right; } if(y.Left.Color == RedBlackSTMNode.BLACK && y.Right.Color == RedBlackSTMNode.BLACK) { // children are both black y.Color = RedBlackSTMNode.RED; // change parent to red x = x.Parent; // move up the tree } else { if(y.Right.Color == RedBlackSTMNode.BLACK) { y.Left.Color = RedBlackSTMNode.BLACK; y.Color = RedBlackSTMNode.RED; RotateRight(y); y = x.Parent.Right; } y.Color = x.Parent.Color; x.Parent.Color = RedBlackSTMNode.BLACK; y.Right.Color = RedBlackSTMNode.BLACK; RotateLeft(x.Parent); x = rbTree; } } else { // right subtree - same as code above with right and left swapped y = x.Parent.Left; if (y.Color == RedBlackSTMNode.RED) { y.Color = RedBlackSTMNode.BLACK; x.Parent.Color = RedBlackSTMNode.RED; RotateRight (x.Parent); y = x.Parent.Left; } if(y.Right.Color == RedBlackSTMNode.BLACK && y.Left.Color == RedBlackSTMNode.BLACK) { y.Color = RedBlackSTMNode.RED; x = x.Parent; } else { if(y.Left.Color == RedBlackSTMNode.BLACK) { y.Right.Color = RedBlackSTMNode.BLACK; y.Color = RedBlackSTMNode.RED; RotateLeft(y); y = x.Parent.Left; } y.Color = x.Parent.Color; x.Parent.Color = RedBlackSTMNode.BLACK; y.Left.Color = RedBlackSTMNode.BLACK; RotateRight(x.Parent); x = rbTree; } } } x.Color = RedBlackSTMNode.BLACK; }
long RedBlackSTMVerify2(RedBlackSTMNode root, long depth) { long height_left; long height_right; if (root == RedBlackSTM.sentinelNode) { return 1; } height_left = RedBlackSTMVerify2(root.Left, depth + 1); height_right = RedBlackSTMVerify2(root.Right, depth + 1); if (height_left == 0 || height_right == 0) { return 0; } if (height_left != height_right) { Console.WriteLine("WARNING: Imbalance @depth={0} : {1} {2}\n", depth, height_left, height_right); } if (root.Left != RedBlackSTM.sentinelNode && root.Left.Parent != root) { Console.WriteLine("lineage(?)\n"); } if (root.Right != RedBlackSTM.sentinelNode && root.Right.Parent != root) { Console.WriteLine("lineage(?)\n"); } // Red-Black alternation if (root.Color == RedBlackSTMNode.RED) { if (root.Left != RedBlackSTM.sentinelNode && root.Left.Color != RedBlackSTMNode.BLACK) { Console.WriteLine("verify1(?)\n"); return 0; } if (root.Right != RedBlackSTM.sentinelNode && root.Right.Color != RedBlackSTMNode.BLACK) { Console.WriteLine("verify2(?)\n"); return 0; } return height_left; } if (root.Color != RedBlackSTMNode.BLACK) { Console.WriteLine("verify3(?)\n"); return 0; } return (height_left + 1); }
private void DebugPrint(IComparable key, String msg, RedBlackSTMNode node) { if ((int)key == 221) { Console.WriteLine(msg); //MonoEmbed.PrintVBoxes(node); } }
///<summary> /// Delete /// Delete a node from the tree and restore red black properties ///<summary> private void Delete(RedBlackSTMNode z) { // 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 RedBlackSTMNode x = new RedBlackSTMNode(); // work node to contain the replacement node RedBlackSTMNode y; // work node // find the replacement node (the successor to x) - the node one with // at *most* one child. if(z.Left == sentinelNode || z.Right == sentinelNode) 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 != sentinelNode) // 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 != sentinelNode) 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 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 == RedBlackSTMNode.BLACK) { RestoreAfterDelete(x); } lastNodeFound = sentinelNode; }
private static RedBlackSTMNode NodeSuccessor(RedBlackSTMNode node) { if (node == RedBlackSTM.sentinelNode) return RedBlackSTM.sentinelNode; else if (node.Right != RedBlackSTM.sentinelNode) { RedBlackSTMNode p = node.Right; while (p.Left != RedBlackSTM.sentinelNode) { p = p.Left; } return p; } else { RedBlackSTMNode p = node.Parent; RedBlackSTMNode ch = node; while (p != null && ch == p.Right) { ch = p; p = p.Parent; } return p; } }
static RedBlackSTM() { sentinelNode = new RedBlackSTMNode(); }
///<summary> /// RotateRight /// Rebalance the tree by rotating the nodes to the right ///</summary> public void RotateRight(RedBlackSTMNode 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). RedBlackSTMNode 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 != sentinelNode) y.Right.Parent = x; // sets y's Right Parent to x if(y != sentinelNode) 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 != sentinelNode) // set y as x's Parent x.Parent = y; }
///<summary> /// GetMinKey /// Returns the minimum key value ///<summary> public IComparable GetMinKey() { RedBlackSTMNode treeNode = rbTree; if(treeNode == null || treeNode == sentinelNode) throw(new RedBlackSTMException("RedBlackSTM tree is empty")); // traverse to the extreme left to find the smallest key while(treeNode.Left != sentinelNode) treeNode = treeNode.Left; lastNodeFound = treeNode; return treeNode.Key; }
///<summary> /// GetData /// Gets the data object associated with the specified key ///<summary> public object GetData(IComparable key) { int result; RedBlackSTMNode treeNode = rbTree; // begin at root // traverse tree until node is found while(treeNode != sentinelNode) { result = key.CompareTo(treeNode.Key); if(result == 0) { lastNodeFound = treeNode; //MonoEmbed.PrintVBoxes(treeNode); return treeNode.Data; } if(result < 0) treeNode = treeNode.Left; else treeNode = treeNode.Right; } return null; //throw(new RedBlackSTMException("RedBlackSTMNode key was not found")); }
///<summary> /// Clear /// Empties or clears the tree ///<summary> public void Clear() { rbTree = sentinelNode; intCount = 0; }
///<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 bool Add(IComparable key, object data) { //if ((int)key == 219 || (int)key == 220) // MonoEmbed.BreakpointTest(); if (key == null || data == null) throw(new RedBlackSTMException("RedBlackSTMNode key and data must not be null")); // traverse tree - find where node belongs int result = 0; // create new node RedBlackSTMNode node = new RedBlackSTMNode(); RedBlackSTMNode temp = rbTree; // grab the rbTree node of the tree while(temp != sentinelNode) { // find Parent node.Parent = temp; result = key.CompareTo(temp.Key); if (result == 0) return false; //throw(new RedBlackSTMException("A Node with the same key already exists")); if(result > 0) temp = temp.Right; else temp = temp.Left; } // setup node node.Key = key; node.Data = data; node.Left = sentinelNode; node.Right = sentinelNode; // insert node into tree starting at parent's location if(node.Parent != null) { result = node.Key.CompareTo(node.Parent.Key); if(result > 0) node.Parent.Right = node; else node.Parent.Left = node; } else rbTree = node; // first node added RestoreAfterInsert(key, node); // restore red-black properities lastNodeFound = node; intCount = intCount + 1; return true; }