// 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); } }
public void Between(RbKey loKey, RbKey hiKey, out int count, out error err) { count = 0; err = null; if (loKey == null) { err = ErrorDef.ArgumentNilError("loKey"); return; } if (hiKey == null) { err = ErrorDef.ArgumentNilError("hiKey"); return; } RbTree tree; this.checkStateAndGetTree(out tree, out err); if (err != null) { return; } try { var cmp = loKey.ComparedTo(hiKey); switch (cmp) { case KeyComparison.KeysAreEqual: var node = tree.find(loKey); if (node != null) { count = 1; this.callback(this, node.key, node.value); return; } return; case KeyComparison.KeyIsGreater: var tmp = loKey; loKey = hiKey; hiKey = tmp; break; } this.walkBetween(tree.root, loKey, hiKey); count = this.CurrentCount(); } finally { Interlocked.CompareExchange(ref this.state, (long)IterationState.iteratorReady, (long)IterationState.iteratorWalking); } }
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); } } }
// find returns the node if (key found, otherwise returns null internal rbNode find(RbKey key) { for (var node = this.root; node != null;) { var cmp = key.ComparedTo(node.key); switch (cmp) { case KeyComparison.KeyIsLess: node = node.left; break; case KeyComparison.KeyIsGreater: node = node.right; break; default: return(node); } } return(null); }
// 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)); }