private static Node Insert(Node root, Node newNode, int newNodeStart, IIntervalIntrospector <T> introspector) { if (root == null) { return(newNode); } Node newLeft, newRight; if (newNodeStart < introspector.GetStart(root.Value)) { newLeft = Insert(root.Left, newNode, newNodeStart, introspector); newRight = root.Right; } else { newLeft = root.Left; newRight = Insert(root.Right, newNode, newNodeStart, introspector); } root.SetLeftRight(newLeft, newRight, introspector); var newRoot = root; return(Balance(newRoot, introspector)); }
public ContextIntervalTree(IIntervalIntrospector <T> introspector) : base(introspector, values: null) { _edgeExclusivePredicate = ContainsEdgeExclusive; _edgeInclusivePredicate = ContainsEdgeInclusive; _containPredicate = (value, start, end) => Contains(value, start, end, Introspector); }
public IntervalTree(IIntervalIntrospector <T> introspector, IEnumerable <T> values) { foreach (var value in values) { root = Insert(root, new Node(value), introspector); } }
internal void SetLeftRight(Node left, Node right, IIntervalIntrospector <T> introspector) { this.Left = left; this.Right = right; this.Height = 1 + Math.Max(Height(left), Height(right)); // We now must store the node that produces the maximum end. Since we might have tracking spans (or // something similar) defining our values of "end", we can't store the int itself. var thisEndValue = GetEnd(this.Value, introspector); var leftEndValue = MaxEndValue(left, introspector); var rightEndValue = MaxEndValue(right, introspector); if (thisEndValue >= leftEndValue && thisEndValue >= rightEndValue) { MaxEndNode = this; } else if ((leftEndValue >= rightEndValue) && left != null) { MaxEndNode = left.MaxEndNode; } else if (right != null) { MaxEndNode = right.MaxEndNode; } else { Contract.Fail("We have no MaxEndNode? Huh?"); } }
public ContextIntervalTree(IIntervalIntrospector <T> introspector) : base(introspector) { this.edgeExclusivePredicate = ContainsEdgeExclusive; this.edgeInclusivePredicate = ContainsEdgeInclusive; this.containPredicate = (value, start, end) => Contains(value, start, end, Introspector, skipZeroLengthIntervals: true); }
private static Node Balance(Node node, IIntervalIntrospector <T> introspector) { int balanceFactor = BalanceFactor(node); if (balanceFactor == -2) { int rightBalance = BalanceFactor(node.Right); if (rightBalance == -1) { return(node.LeftRotation(introspector)); } else { Contract.Requires(rightBalance == 1); return(node.InnerRightOuterLeftRotation(introspector)); } } else if (balanceFactor == 2) { int leftBalance = BalanceFactor(node.Left); if (leftBalance == 1) { return(node.RightRotation(introspector)); } else { Contract.Requires(leftBalance == -1); return(node.InnerLeftOuterRightRotation(introspector)); } } return(node); }
// Sample: // 1 2 // / \ / \ // a 2 1 3 // / \ => / \ / \ // b 3 a b c d // / \ // c d internal Node LeftRotation(IIntervalIntrospector <T> introspector) { var oldRight = this.Right; this.SetLeftRight(this.Left, this.Right.Left, introspector); oldRight.SetLeftRight(this, oldRight.Right, introspector); return(oldRight); }
public IntervalTree(IIntervalIntrospector <T> introspector, IEnumerable <T> values) : this(root : null) { foreach (var value in values) { root = Insert(root, new Node(introspector, value), introspector, inPlace : true); } }
protected SimpleIntervalTree(IIntervalIntrospector <T> introspector, Node root) : base(root) { if (introspector == null) { throw new ArgumentNullException("introspector"); } this.introspector = introspector; }
private static bool IntersectsWith(T value, int start, int length, IIntervalIntrospector <T> introspector) { var otherStart = start; var otherEnd = start + length; var thisEnd = GetEnd(value, introspector); var thisStart = introspector.GetStart(value); return(otherStart <= thisEnd && otherEnd >= thisStart); }
// Sample: // 1 1 3 // / \ / \ / \ // 2 d 3 d 2 1 // / \ => / \ => / \ / \ // a 3 2 c a b c d // / \ / \ // b c a b internal Node InnerLeftOuterRightRotation(IIntervalIntrospector <T> introspector) { var newTop = this.Left.Right; var oldLeft = this.Left; this.SetLeftRight(this.Left.Right.Right, this.Right, introspector); oldLeft.SetLeftRight(oldLeft.Left, oldLeft.Right.Left, introspector); newTop.SetLeftRight(oldLeft, this, introspector); return(newTop); }
public SimpleIntervalTree(IIntervalIntrospector <T> introspector, IEnumerable <T> values) { _introspector = introspector; if (values != null) { foreach (var value in values) { root = Insert(root, new Node(value), introspector); } } }
protected static bool Contains(T value, int start, int length, IIntervalIntrospector <T> introspector) { var otherStart = start; var otherEnd = start + length; var thisEnd = GetEnd(value, introspector); var thisStart = introspector.GetStart(value); // make sure "Contains" test to be same as what TextSpan does if (length == 0) { return(thisStart <= otherStart && otherEnd < thisEnd); } return(thisStart <= otherStart && otherEnd <= thisEnd); }
private static bool IntersectsWith(T value, int start, int length, IIntervalIntrospector <T> introspector, bool skipZeroLengthIntervals) { var otherStart = start; var otherEnd = start + length; var thisEnd = GetEnd(value, introspector); var thisStart = introspector.GetStart(value); if (thisStart == thisEnd && skipZeroLengthIntervals) { return(false); } return(otherStart <= thisEnd && otherEnd >= thisStart); }
private static bool OverlapsWith(T value, int start, int length, IIntervalIntrospector <T> introspector) { var otherStart = start; var otherEnd = start + length; var thisEnd = GetEnd(value, introspector); var thisStart = introspector.GetStart(value); if (length == 0) { return(thisStart < otherStart && otherStart < thisEnd); } int overlapStart = Math.Max(thisStart, otherStart); int overlapEnd = Math.Min(thisEnd, otherEnd); return(overlapStart < overlapEnd); }
// Sample: // 1 2 // / \ / \ // a 2 1 3 // / \ => / \ / \ // b 3 a b c d // / \ // c d internal Node LeftRotation(bool inPlace, IIntervalIntrospector <T> introspector) { if (inPlace) { var oldRight = this.Right; this.SetLeftRight(this.Left, this.Right.Left, introspector); oldRight.SetLeftRight(this, oldRight.Right, introspector); return(oldRight); } else { var newLeft = this.With( this.Left, this.Right.Left, introspector); var newRight = this.Right.Right; return(this.Right.With(newLeft, newRight, introspector)); } }
// Sample: // 1 1 3 // / \ / \ / \ // 2 d 3 d 2 1 // / \ => / \ => / \ / \ // a 3 2 c a b c d // / \ / \ // b c a b internal Node InnerLeftOuterRightRotation(bool inPlace, IIntervalIntrospector <T> introspector) { if (inPlace) { var newTop = this.Left.Right; var oldLeft = this.Left; this.SetLeftRight(this.Left.Right.Right, this.Right, introspector); oldLeft.SetLeftRight(oldLeft.Left, oldLeft.Right.Left, introspector); newTop.SetLeftRight(oldLeft, this, introspector); return(newTop); } else { var temp = this.With( this.Left.LeftRotation(inPlace, introspector), this.Right, introspector); return(temp.RightRotation(inPlace, introspector)); } }
public static SimpleIntervalTree <T> Create <T>(IIntervalIntrospector <T> introspector, params T[] values) { return(Create(introspector, (IEnumerable <T>)values)); }
internal Node(IIntervalIntrospector <T> introspector, T value, Node left, Node right) { this.Value = value; SetLeftRight(left, right, introspector); }
protected static Node Insert(Node root, Node newNode, IIntervalIntrospector <T> introspector) { var newNodeStart = introspector.GetStart(newNode.Value); return(Insert(root, newNode, newNodeStart, introspector)); }
public bool IntersectsWith(int position, IIntervalIntrospector <T> introspector) { return(GetIntersectingIntervals(position, 0, introspector).Any()); }
private IEnumerable <T> GetInOrderIntervals(int start, int length, TestInterval testInterval, IIntervalIntrospector <T> introspector) { if (root == null) { yield break; } var end = start + length; // The bool indicates if this is the first time we are seeing the node. var candidates = new Stack <ValueTuple <Node, bool> >(); candidates.Push(ValueTuple.Create(root, true)); while (candidates.Count > 0) { var currentTuple = candidates.Pop(); var currentNode = currentTuple.Item1; Debug.Assert(currentNode != null); var firstTime = currentTuple.Item2; if (!firstTime) { // We're seeing this node for the second time (as we walk back up the left // side of it). Now see if it matches our test, and if so return it out. if (testInterval(currentNode.Value, start, length, introspector)) { yield return(currentNode.Value); } } else { // First time we're seeing this node. In order to see the node 'in-order', // we push the right side, then the node again, then the left side. This // time we mark the current node with 'false' to indicate that it's the // second time we're seeing it the next time it comes around. // right children's starts will never be to the left of the parent's start // so we should consider right subtree only if root's start overlaps with // interval's End, if (introspector.GetStart(currentNode.Value) <= end) { var right = currentNode.Right; if (right != null && GetEnd(right.MaxEndNode.Value, introspector) >= start) { candidates.Push(ValueTuple.Create(right, true)); } } candidates.Push(ValueTuple.Create(currentNode, false)); // only if left's maxVal overlaps with interval's start, we should consider // left subtree var left = currentNode.Left; if (left != null && GetEnd(left.MaxEndNode.Value, introspector) >= start) { candidates.Push(ValueTuple.Create(left, true)); } } } }
internal Node With(Node left, Node right, IIntervalIntrospector <T> introspector) { return(new Node(introspector, this.Value, left, right)); }
internal Node(IIntervalIntrospector <T> introspector, T interval) : this(introspector, interval, left : null, right : null) { }
protected static int MaxEndValue(Node node, IIntervalIntrospector <T> arg) { return(node == null ? 0 : GetEnd(node.MaxEndNode.Value, arg)); }
public SimpleIntervalTree(IIntervalIntrospector <T> introspector) : this(introspector, root : null) { }
public static SimpleIntervalTree <T> Create <T>(IIntervalIntrospector <T> introspector, IEnumerable <T> values = null) { return(new SimpleIntervalTree <T>(introspector, values)); }
public IEnumerable <T> GetContainingIntervals(int start, int length, IIntervalIntrospector <T> introspector) { return(this.GetInOrderIntervals(start, length, s_containsTest, introspector)); }
public IEnumerable <T> GetIntersectingIntervals(int start, int length, IIntervalIntrospector <T> introspector) { return(this.GetInOrderIntervals(start, length, s_intersectsWithTest, introspector)); }
protected static int GetEnd(T value, IIntervalIntrospector <T> introspector) { return(introspector.GetStart(value) + introspector.GetLength(value)); }