public void walkLessOrEqual(rbNode node, RbKey key) { if (node == null || !this.inWalk()) { return; } if (node.left != null) { this.walkLessOrEqual(node.left, key); if (!this.inWalk()) { return; } } var cmp = node.key.ComparedTo(key); if (cmp == KeyComparison.KeyIsLess || cmp == KeyComparison.KeysAreEqual) { this.incrementCount(); this.callback(this, node.key, node.value); if (!this.inWalk()) { return; } if (node.right != null) { this.walkLessOrEqual(node.right, key); } } }
public void walkGreaterThan(rbNode node, RbKey key) { if (node == null || !this.inWalk()) { return; } if (node.key.ComparedTo(key) == KeyComparison.KeyIsGreater) { if (node.left != null) { this.walkGreaterThan(node.left, key); if (!this.inWalk()) { return; } } this.incrementCount(); this.callback(this, node.key, node.value); if (!this.inWalk()) { return; } } if (node.right != null) { this.walkGreaterThan(node.right, key); } }
public void walkAll(rbNode node) { if (node == null || !this.inWalk()) { return; } if (node.left != null) { this.walkAll(node.left); if (!this.inWalk()) { return; } } this.incrementCount(); this.callback(this, node.key, node.value); if (!this.inWalk()) { return; } if (node.right != null) { this.walkAll(node.right); } }
// insertNode adds the given key and value into the node private rbNode insertNode(rbNode node, RbKey key, object value) { if (node == null) { this.count++; return(newRbNode(key, value)); } var cmp = key.ComparedTo(node.key); switch (cmp) { case KeyComparison.KeyIsLess: node.left = this.insertNode(node.left, key, value); break; case KeyComparison.KeyIsGreater: node.right = this.insertNode(node.right, key, value); break; default: if (this.onInsert == null) { node.value = value; } else { node.value = this.onInsert(key, value); } break; } return(balance(node)); }
// ceilig returns the smallest key node in the subtree rooted at x greater than or equal to the given key private rbNode ceiling(rbNode node, RbKey key) { if (node == null) { return(null); } var cmp = key.ComparedTo(node.key); switch (cmp) { case KeyComparison.KeysAreEqual: return(node); case KeyComparison.KeyIsGreater: return(ceiling(node.right, key)); default: var cn = ceiling(node.left, key); if (cn != null) { return(cn); } return(node); } }
// floor returns the largest key node in the subtree rooted at x less than or equal to the given key private rbNode floor(rbNode node, RbKey key) { if (node == null) { return(null); } var cmp = key.ComparedTo(node.key); switch (cmp) { case KeyComparison.KeysAreEqual: return(node); case KeyComparison.KeyIsLess: return(floor(node.left, key)); default: var fn = floor(node.right, key); if (fn != null) { return(fn); } return(node); } }
// Delete deletes the given key from the tree public void Delete(RbKey key) { this.root = this.deleteNode(this.root, key); if (this.root != null) { this.root.color = black; } }
// Insert inserts the given key and value into the tree public void Insert(RbKey key, object value) { if (key != null) { this.root = this.insertNode(this.root, key, value); this.root.color = black; } }
// newRbNode creates a new rbNode and returns its address private rbNode newRbNode(RbKey key, object value) { var result = new rbNode { key = key, value = value, color = red, }; return(result); }
// moveRedRight makes node.right or one of its children red, // assuming that node is red and both children are black. private rbNode moveRedRight(rbNode node) { colorFlip(node); if (isRed(node.left.left)) { node = rotateRight(node); colorFlip(node); } return(node); }
// flipColor switchs the color of the node from red to black or black to red private void flipColor(rbNode node) { if (node.color == black) { node.color = red; } else { node.color = black; } }
// max finds the greatest node key including the given node private rbNode max(rbNode node) { if (node != null) { for (; node.right != null;) { node = node.right; } } return(node); }
// min finds the smallest node key including the given node private rbNode min(rbNode node) { if (node != null) { for (; node.left != null;) { node = node.left; } } return(node); }
// rotateRight makes a left-leaning link lean to the right private rbNode rotateRight(rbNode node) { var child = node.left; node.left = child.right; child.right = node; child.color = node.color; node.color = red; return(child); }
// deleteMin removes the smallest key and associated value from the tree private rbNode deleteMin(rbNode node) { if (node.left == null) { return(null); } if (isBlack(node.left) && !isRed(node.left.left)) { node = moveRedLeft(node); } node.left = deleteMin(node.left); return(balance(node)); }
// balance restores red-black tree invariant private rbNode balance(rbNode node) { if (isRed(node.right)) { node = rotateLeft(node); } if (isRed(node.left) && isRed(node.left.left)) { node = rotateRight(node); } if (isRed(node.left) && isRed(node.right)) { colorFlip(node); } return(node); }
public void walkBetween(rbNode node, RbKey loKey, RbKey hiKey) { if (node == null || !this.inWalk()) { return; } var cmpLo = (int)loKey.ComparedTo(node.key); if (cmpLo < RbTree.zeroOrEqual) { if (node.left != null) { this.walkBetween(node.left, loKey, hiKey); if (!this.inWalk()) { return; } } } var cmpHi = (int)hiKey.ComparedTo(node.key); if (cmpLo <= RbTree.zeroOrEqual && cmpHi >= RbTree.zeroOrEqual) { this.incrementCount(); this.callback(this, node.key, node.value); if (!this.inWalk()) { return; } } if (cmpHi > RbTree.zeroOrEqual) { if (node.right != null) { this.walkBetween(node.right, loKey, hiKey); } } }
// isRed checks if (node exists and its color is red private bool isRed(rbNode node) { return(node != null && node.color == red); }
// colorFlip switchs the color of the node and its children from red to black or black to red private void colorFlip(rbNode node) { flipColor(node); flipColor(node.left); flipColor(node.right); }
// deleteNode deletes the given key from the node private rbNode deleteNode(rbNode node, RbKey key) { if (node == null) { return(null); } var cmp = key.ComparedTo(node.key); if (cmp == KeyComparison.KeyIsLess) { if (isBlack(node.left) && !isRed(node.left.left)) { node = moveRedLeft(node); } node.left = this.deleteNode(node.left, key); } else { if (cmp == KeyComparison.KeysAreEqual && this.onDelete != null) { var value = this.onInsert(key, node.value); if (value != null) { node.value = value; return(node); } } if (isRed(node.left)) { node = rotateRight(node); } if (isBlack(node.right) && !isRed(node.right.left)) { node = moveRedRight(node); } if (key.ComparedTo(node.key) != KeyComparison.KeysAreEqual) { node.right = this.deleteNode(node.right, key); } else { if (node.right == null) { return(null); } var rm = min(node.right); node.key = rm.key; node.value = rm.value; node.right = deleteMin(node.right); rm.left = null; rm.right = null; this.count--; } } return(balance(node)); }
// isBlack checks if (node exists and its color is black private bool isBlack(rbNode node) { return(node != null && node.color == black); }