/// <summary> /// Tests whether the given value is a member of the <see cref="DisjointSet"/>. /// </summary> /// <param name="left">The <see cref="DisjointSet"/> to examine.</param> /// <param name="right">The value to test for membership.</param> /// <returns> /// <c>true</c> if the value is contained in any <see cref="Range"/> /// of the <see cref="DisjointSet"/>. /// </returns> public static bool Contains(ref DisjointSet left, ulong right) { return((left == null) ? false : (left = Splay(left.Find(right))).Value & right); }
private DisjointSet Insert(Range value) { checked { for (DisjointSet p = this, q; ; p = q) { // If the new range is strictly less than or greater than the // existing range and is not *adjacent*, descend down the left // or right subtree like a normal binary-tree search. If there // is no appropriate subtree, insert a brand new node. if (value.Max < p.Value.Min - (p.Value.Min > ulong.MinValue ? 1ul : 0ul)) { q = p.Left; if (q == null) { p.Left = new DisjointSet(null, value, null); p.Left.Parent = p; return(p.Left); } } else if (value.Min > p.Value.Max + (p.Value.Max < ulong.MaxValue ? 1ul : 0ul)) { q = p.Right; if (q == null) { p.Right = new DisjointSet(null, value, null); p.Right.Parent = p; return(p.Right); } } // But if the ranges overlap or are adjacent, we've found our mark. else { // Get the left and right subtrees. DisjointSet left = p.Left, right = p.Right; // Eliminate all subtrees that overlap or are adjacent to the new range. // Detach the subtrees so we can splay them. // Splay each subtree so the value for comparison will be at the top. // Each time, adjust the new range if the existing ranges extend the bounds. if (left != null) { do { DisjointSet parent = left.Parent; left.Parent = null; left = Splay(left.Find(value.Min)); left.Parent = Parent; if (value.Min <= left.Value.Max + (left.Value.Max < ulong.MaxValue ? 1ul : 0ul)) { value = new Range(Math.Min(value.Min, left.Value.Min), value.Max); left = left.Left; } else { break; } } while (left != null); } if (right != null) { do { DisjointSet parent = right.Parent; right.Parent = null; right = Splay(right.Find(value.Max)); right.Parent = parent; if (right.Value.Min - (right.Value.Min > ulong.MinValue ? 1ul : 0ul) <= value.Max) { value = new Range(value.Min, Math.Max(value.Max, right.Value.Max)); right = right.Right; } else { break; } } while (right != null); } // Now extend the bounds of the range at the root of the tree. p.Value = new Range(Math.Min(value.Min, p.Value.Min), Math.Max(value.Max, p.Value.Max)); // Reattach the eliminated subtrees' branches, which are now not adjacent to the new value. p.Left = left; p.Right = right; // Reattach their parents. if (left != null) { left.Parent = p; left.AssertWellOrdered(); } if (right != null) { right.Parent = p; right.AssertWellOrdered(); } // Return the "inserted" node. p.AssertWellOrdered(); return(p); } } } }
/// <summary> /// Tests whether the given value is a member of the <see cref="DisjointSet"/>. /// </summary> /// <param name="left">The <see cref="DisjointSet"/> to examine.</param> /// <param name="right">The value to test for membership.</param> /// <returns> /// <c>true</c> if the value is contained in any <see cref="Range"/> /// of the <see cref="DisjointSet"/>. /// </returns> public static bool Contains(ref DisjointSet left, ulong right) { return (left == null) ? false : (left = Splay(left.Find(right))).Value & right; }