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)); }
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); }
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); }
private IEnumerable <T> GetPreOrderIntervals(int start, int length, TestInterval testInterval, IIntervalIntrospector <T> introspector, bool skipZeroLengthIntervals) { if (root == null || GetEnd(root.MaxEndNode.Value, introspector) < start) { yield break; } int end = start + length; var candidates = new Stack <Node>(); candidates.Push(root); while (candidates.Count != 0) { var currentNode = candidates.Pop(); // 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(right); } } // 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(left); } if (testInterval(currentNode.Value, start, length, introspector, skipZeroLengthIntervals)) { yield return(currentNode.Value); } } }
protected static int GetEnd(T value, IIntervalIntrospector <T> introspector) { return(introspector.GetStart(value) + introspector.GetLength(value)); }
protected static Node Insert(Node root, Node newNode, IIntervalIntrospector <T> introspector) { var newNodeStart = introspector.GetStart(newNode.Value); return(Insert(root, newNode, newNodeStart, introspector)); }
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)); } } } }
private IList <T> GetInOrderIntervals(int start, int length, TestInterval testInterval, IIntervalIntrospector <T> introspector, bool skipZeroLengthIntervals) { List <T> result = null; if (root != null && GetEnd(root.MaxEndNode.Value, introspector) >= start) { int end = start + length; var candidates = new Stack <Node>(); var currentNode = root; while (true) { if (currentNode != null) { candidates.Push(currentNode); // 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) { currentNode = left; continue; } // current node has no meaning now, set it to null currentNode = null; } if (candidates.Count == 0) { break; } currentNode = candidates.Pop(); if (testInterval(currentNode.Value, start, length, introspector, skipZeroLengthIntervals)) { result = result ?? new List <T>(); result.Add(currentNode.Value); } // 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) { currentNode = right; continue; } } // set to null to get new one from stack currentNode = null; } } return(result ?? SpecializedCollections.EmptyList <T>()); }