// <summary>Return number of nodes of current sub-tree containing // element. Uses IComparer <paramref name='cmp '/> to find and to // check equality.</summary> // <param name='element'></param> // <param name='cmp'>An IComparer object.</param> // <returns>A 32-bit signed integer.</returns> public int count(T element, IComparer <T> cmp) { var c = 0; RBCell t = this; while (t != null) { int diff = cmp.Compare(element, t.element()); if (diff == 0) { ++c; if (t.leftValue == null) { t = t.rightValue; } else if (t.rightValue == null) { t = t.leftValue; } else { c += t.rightValue.count(element, cmp); t = t.leftValue; } } else { t = (diff < 0) ? t.leftValue : t.rightValue; } } return(c); }
/** From CLR **/ private RBCell rotateLeft(RBCell rootValue) { RBCell r = this.rightValue; this.rightValue = r.leftValue; if (r.leftValue != null) { r.leftValue.parentValue = this; } r.parentValue = this.parentValue; if (this.parentValue == null) { rootValue = r; } else if (this.parentValue.leftValue == this) { this.parentValue.leftValue = r; } else { this.parentValue.rightValue = r; } r.leftValue = this; this.parentValue = r; return(rootValue); }
// <summary>Set the color of node p, or do nothing if p is // null.</summary> // <param name='p'></param> // <param name='c'>A Boolean object.</param> private static void setColor(RBCell p, bool c) { if (p != null) { p.colorValue = c; } }
/** From CLR **/ private RBCell rotateRight(RBCell rootValue) { RBCell l = this.leftValue; this.leftValue = l.rightValue; if (l.rightValue != null) { l.rightValue.parentValue = this; } l.parentValue = this.parentValue; if (this.parentValue == null) { rootValue = l; } else if (this.parentValue.rightValue == this) { this.parentValue.rightValue = l; } else { this.parentValue.leftValue = l; } l.rightValue = this; this.parentValue = l; return(rootValue); }
// <summary>Copies this object's data to a new array.</summary> // <param name='array'>A T[] object.</param> // <param name='arrayIndex'>Starting index to copy to.</param> public void CopyTo(T[] array, int arrayIndex) { if (array == null) { throw new ArgumentNullException("array"); } if (arrayIndex < 0) { throw new ArgumentException("arrayIndex (" + arrayIndex + ") is less than 0"); } if (this.treeValue != null) { RBCell t = this.treeValue.leftmost(); while (t != null && arrayIndex < array.Length) { T v = t.element(); if (arrayIndex >= 0 && arrayIndex < array.Length) { array[arrayIndex] = v; } ++arrayIndex; t = t.successor(); } } }
// <summary>Return the minimum element of the current // (sub)tree.</summary> // <returns>A RBCell object.</returns> public RBCell leftmost() { RBCell p = this; for (; p.leftValue != null; p = p.leftValue) { } return(p); }
// <summary>Return the root (parentless node) of the tree.</summary> // <returns>A RBCell object.</returns> public RBCell root() { RBCell p = this; for (; p.parentValue != null; p = p.parentValue) { } return(p); }
// <summary>Return the maximum element of the current // (sub)tree.</summary> // <returns>A RBCell object.</returns> public RBCell rightmost() { RBCell p = this; for (; p.rightValue != null; p = p.rightValue) { } return(p); }
// helper methods private bool addInternal(T element, OccurrenceMode checkOccurrence) { if (this.treeValue == null) { this.treeValue = new RBCell(element); this.incCount(); } else { RBCell t = this.treeValue; for (;;) { int diff = this.cmpValue.Compare(element, t.element()); if (diff == 0 && checkOccurrence == OccurrenceMode.AddIfMissing) { return(false); } if (diff == 0 && checkOccurrence == OccurrenceMode.OverwriteIfExisting) { t.element(element); return(false); } if (diff <= 0) { if (t.left() != null) { t = t.left(); } else { this.treeValue = t.insertLeft( new RBCell(element), this.treeValue); this.incCount(); return(true); } } else { if (t.right() != null) { t = t.right(); } else { this.treeValue = t.insertRight( new RBCell(element), this.treeValue); this.incCount(); return(true); } } } } return(true); }
// <summary>Implements collections.UpdatableCollection.take. Time // complexity: O(log n). Takes the least element. @see // collections.UpdatableCollection#take.</summary> // <returns>A T object.</returns> public T Pop() { if (this.countValue != 0) { RBCell p = this.treeValue.leftmost(); T v = p.element(); this.treeValue = p.delete(this.treeValue); this.decCount(); return(v); } return(default(T)); }
private IEnumerable <T> Iterator() { if (this.treeValue != null) { RBCell t = this.treeValue.leftmost(); while (t != null) { T v = t.element(); yield return(v); t = t.successor(); } } }
public bool Find(T element, out T outval) { if (this.countValue == 0) { outval = default(T); return(false); } RBCell cell = this.treeValue.find(element, this.cmpValue); if (cell == null) { outval = default(T); return(false); } outval = cell.element(); return(true); }
// <summary>Return node of current sub-tree containing element as // element(), if it exists, else null. Uses IComparer <paramref // name='cmp '/> to find and to check equality.</summary> // <param name='element'></param> // <param name='cmp'>An IComparer object.</param> // <returns>A RBCell object.</returns> public RBCell find(T element, IComparer <T> cmp) { RBCell t = this; for (;;) { int diff = cmp.Compare(element, t.element()); if (diff == 0) { return(t); } t = (diff < 0) ? t.leftValue : t.rightValue; if (t == null) { return(null); } } }
// <summary>Return the in-order predecessor, or null if no // such.</summary> // <returns>A RBCell object.</returns> public RBCell predecessor() { if (this.leftValue != null) { return(this.leftValue.rightmost()); } else { RBCell p = this.parentValue; RBCell ch = this; while (p != null && ch == p.leftValue) { { ch = p; } p = p.parentValue; } return(p); } }
private bool remove_(T element, bool allOccurrences) { var ret = false; while (this.countValue > 0) { RBCell p = this.treeValue.find(element, this.cmpValue); if (p != null) { this.treeValue = p.delete(this.treeValue); this.decCount(); ret = true; if (!allOccurrences) { return(ret); } } else { break; } } return(ret); }
/** From CLR **/ private RBCell fixAfterInsertion(RBCell rootValue) { this.colorValue = RED; RBCell x = this; while (x != null && x != rootValue && !x.parentValue.colorValue) { if (parentOf(x) == leftOf(parentOf(parentOf(x)))) { RBCell y = rightOf(parentOf(parentOf(x))); if (!colorOf(y)) { setColor(parentOf(x), BLACK); setColor(y, BLACK); setColor(parentOf(parentOf(x)), RED); x = parentOf(parentOf(x)); } else { if (x == rightOf(parentOf(x))) { x = parentOf(x); rootValue = x.rotateLeft(rootValue); } setColor(parentOf(x), BLACK); setColor(parentOf(parentOf(x)), RED); if (parentOf(parentOf(x)) != null) { rootValue = parentOf(parentOf(x)).rotateRight(rootValue); } } } else { RBCell y = leftOf(parentOf(parentOf(x))); if (!colorOf(y)) { setColor(parentOf(x), BLACK); setColor(y, BLACK); setColor(parentOf(parentOf(x)), RED); x = parentOf(parentOf(x)); } else { if (x == leftOf(parentOf(x))) { x = parentOf(x); rootValue = x.rotateRight(rootValue); } setColor(parentOf(x), BLACK); setColor(parentOf(parentOf(x)), RED); if (parentOf(parentOf(x)) != null) { rootValue = parentOf(parentOf(x)).rotateLeft(rootValue); } } } } rootValue.colorValue = BLACK; return(rootValue); }
// <summary>Return left child of node p, or null if p is // null.</summary> // <param name='p'></param> // <returns>A RBCell object.</returns> private static RBCell leftOf(RBCell p) { return((p == null) ? null : p.leftValue); }
// <summary>Insert cell as the right child of current node, and then // rebalance the tree it is in.</summary> // <param name='cell'>The cell to add.</param> // <param name='root'>The root of the current tree.</param> // <returns>The new root of the current tree. (Rebalancing can change // the root!).</returns> public RBCell insertRight(RBCell cell, RBCell root) { this.rightValue = cell; cell.parentValue = this; return(cell.fixAfterInsertion(root)); }
// <summary>Delete the current node, and then rebalance the tree it is // in.</summary> // <param name='root'>The root of the current tree.</param> // <returns>The new root of the current tree. Rebalancing can change // the root.</returns> public RBCell delete(RBCell root) { // if strictly internal, swap contents with successor and then delete it if (this.leftValue != null && this.rightValue != null) { RBCell s = this.successor(); this.copyContents(s); return(s.delete(root)); } // Start fixup at replacement node, if it exists RBCell replacement = this.leftValue ?? this.rightValue; if (replacement != null) { // link replacement to parent replacement.parentValue = this.parentValue; if (this.parentValue == null) { root = replacement; } else if (this == this.parentValue.leftValue) { this.parentValue.leftValue = replacement; } else { this.parentValue.rightValue = replacement; } // null out links so they are OK to use by fixAfterDeletion this.leftValue = null; this.rightValue = null; this.parentValue = null; // fix replacement if (this.colorValue) { root = replacement.fixAfterDeletion(root); } return(root); } if (this.parentValue == null) // exit if we are the only node // if no children, use self as phantom replacement // and then unlink { return(null); } if (this.colorValue) { root = this.fixAfterDeletion(root); } // Unlink (Couldn't before since fixAfterDeletion needs parent ptr) if (this.parentValue != null) { if (this == this.parentValue.leftValue) { this.parentValue.leftValue = null; } else if (this == this.parentValue.rightValue) { this.parentValue.rightValue = null; } this.parentValue = null; } return(root); }
// <summary>Return right child of node p, or null if p is // null.</summary> // <param name='p'></param> // <returns>A RBCell object.</returns> private static RBCell rightOf(RBCell p) { return((p == null) ? null : p.rightValue); }
// <summary>Copy all content fields from another node.</summary> // <param name='t'></param> private void copyContents(RBCell t) { this.elementValue = t.elementValue; }
// <summary>Return parent of node p, or null if p is null.</summary> // <param name='p'></param> // <returns>A RBCell object.</returns> private static RBCell parentOf(RBCell p) { return((p == null) ? null : p.parentValue); }
/** From CLR **/ private RBCell fixAfterDeletion(RBCell rootValue) { RBCell x = this; while (x != rootValue && colorOf(x)) { if (x == leftOf(parentOf(x))) { RBCell sib = rightOf(parentOf(x)); if (!colorOf(sib)) { setColor(sib, BLACK); setColor(parentOf(x), RED); rootValue = parentOf(x).rotateLeft(rootValue); sib = rightOf(parentOf(x)); } if (colorOf(leftOf(sib)) && colorOf(rightOf(sib))) { setColor(sib, RED); x = parentOf(x); } else { if (colorOf(rightOf(sib))) { setColor(leftOf(sib), BLACK); setColor(sib, RED); rootValue = sib.rotateRight(rootValue); sib = rightOf(parentOf(x)); } setColor(sib, colorOf(parentOf(x))); setColor(parentOf(x), BLACK); setColor(rightOf(sib), BLACK); rootValue = parentOf(x).rotateLeft(rootValue); x = rootValue; } } else // symmetric { RBCell sib = leftOf(parentOf(x)); if (!colorOf(sib)) { setColor(sib, BLACK); setColor(parentOf(x), RED); rootValue = parentOf(x).rotateRight(rootValue); sib = leftOf(parentOf(x)); } if (colorOf(rightOf(sib)) && colorOf(leftOf(sib))) { setColor(sib, RED); x = parentOf(x); } else { if (colorOf(leftOf(sib))) { setColor(rightOf(sib), BLACK); setColor(sib, RED); rootValue = sib.rotateLeft(rootValue); sib = leftOf(parentOf(x)); } setColor(sib, colorOf(parentOf(x))); setColor(parentOf(x), BLACK); setColor(leftOf(sib), BLACK); rootValue = parentOf(x).rotateRight(rootValue); x = rootValue; } } } setColor(x, BLACK); return(rootValue); }
// <summary>Initializes a new instance of the RedBlackTree class. // Special version of constructor needed by clone().</summary> // <param name='cmp'>An IComparer object.</param> // <param name='t'>A RBCell object.</param> // <param name='n'>A 32-bit signed integer.</param> private RedBlackTree(IComparer <T> cmp, RBCell t, int n) { this.countValue = n; this.treeValue = t; this.cmpValue = cmp ?? Comparer <T> .Default; }
// <summary>Implements collections.UpdatableCollection.clear. Time // complexity: O(1). @see // collections.UpdatableCollection#clear.</summary> public void Clear() { this.countValue = 0; this.treeValue = null; }
// <summary>Return color of node p, or BLACK if p is null.</summary> // <param name='p'></param> // <returns>A Boolean object.</returns> private static bool colorOf(RBCell p) { return((p == null) ? BLACK : p.colorValue); }