// Returns ith node public virtual IntervalTree.TreeNode <E, T> GetNode(IntervalTree.TreeNode <E, T> node, int nodeIndex) { int i = nodeIndex; IntervalTree.TreeNode <E, T> n = node; while (n != null) { if (i < 0 || i >= n.size) { return(null); } int leftSize = (n.left != null) ? n.left.size : 0; if (i == leftSize) { return(n); } else { if (i > leftSize) { // Look for in right side of tree n = n.right; i = i - leftSize - 1; } else { n = n.left; } } } return(null); }
// Moves this node up the tree until it replaces the target node public virtual void RotateUp(IntervalTree.TreeNode <E, T> node, IntervalTree.TreeNode <E, T> target) { IntervalTree.TreeNode <E, T> n = node; bool done = false; while (n != null && n.parent != null && !done) { // Check if we are the left or right child done = (n.parent == target); if (n == n.parent.left) { n = RightRotate(n.parent); } else { if (n == n.parent.right) { n = LeftRotate(n.parent); } else { throw new InvalidOperationException("Not on parent's left or right branches."); } } } }
public virtual void Clear() { value = null; maxEnd = null; size = 0; left = null; right = null; }
public TreeNodeIterator(IntervalTree.TreeNode <E, T> node) { this.node = node; if (node.IsEmpty()) { stage = 3; } }
public virtual bool IsAlphaBalanced(IntervalTree.TreeNode <E, T> node, double alpha) { int leftSize = (node.left != null) ? node.left.size : 0; int rightSize = (node.right != null) ? node.right.size : 0; int threshold = (int)(alpha * node.size) + 1; return((leftSize <= threshold) && (rightSize <= threshold)); }
public virtual IntervalTree.TreeNode <E, T> GetRightmostNode(IntervalTree.TreeNode <E, T> node) { IntervalTree.TreeNode <E, T> n = node; while (n.right != null) { n = n.right; } return(n); }
public static IList <T> GetOverlapping <E, T>(IntervalTree.TreeNode <E, T> n, Interval <E> target) where E : IComparable <E> where T : IHasInterval <E> { IList <T> overlapping = new List <T>(); GetOverlapping(n, target, overlapping); return(overlapping); }
public virtual int Height(IntervalTree.TreeNode <E, T> node) { if (node.value == null) { return(0); } int lh = (node.left != null) ? Height(node.left) : 0; int rh = (node.right != null) ? Height(node.right) : 0; return(Math.Max(lh, rh) + 1); }
public static bool Overlaps <E, T>(IntervalTree.TreeNode <E, T> node, Interval <E> target) where E : IComparable <E> where T : IHasInterval <E> { Stack <IntervalTree.TreeNode <E, T> > todo = new Stack <IntervalTree.TreeNode <E, T> >(); todo.Push(node); while (!todo.IsEmpty()) { IntervalTree.TreeNode <E, T> n = todo.Pop(); // Don't search nodes that don't exist if (n == null || n.IsEmpty()) { continue; } // If target is to the right of the rightmost point of any interval // in this node and all children, there won't be any matches. if (target.first.CompareTo(n.maxEnd) > 0) { continue; } // Check this node if (n.value.GetInterval().Overlaps(target)) { return(true); } // Search left children if (n.left != null) { todo.Add(n.left); } // If target is to the left of the start of this interval, // then it can't be in any child to the right. if (target.second.CompareTo(n.value.GetInterval().First()) < 0) { continue; } if (n.right != null) { todo.Add(n.right); } } return(false); }
private static bool Contains <E, T>(IntervalTree.TreeNode <E, T> node, Interval <E> target, IPredicate <T> containsTargetFunction) where E : IComparable <E> where T : IHasInterval <E> { Stack <IntervalTree.TreeNode <E, T> > todo = new Stack <IntervalTree.TreeNode <E, T> >(); todo.Push(node); // Don't search nodes that don't exist while (!todo.IsEmpty()) { IntervalTree.TreeNode <E, T> n = todo.Pop(); // Don't search nodes that don't exist if (n == null || n.IsEmpty()) { continue; } // If target is to the right of the rightmost point of any interval // in this node and all children, there won't be any matches. if (target.first.CompareTo(n.maxEnd) > 0) { continue; } // Check this node if (containsTargetFunction.Test(n.value)) { return(true); } if (n.left != null) { todo.Push(n.left); } // If target is to the left of the start of this interval, then no need to search right if (target.second.CompareTo(n.value.GetInterval().First()) <= 0) { continue; } // Need to check right children if (n.right != null) { todo.Push(n.right); } } return(false); }
public static void GetOverlapping <E, T>(IntervalTree.TreeNode <E, T> node, Interval <E> target, IList <T> result) where E : IComparable <E> where T : IHasInterval <E> { IQueue <IntervalTree.TreeNode <E, T> > todo = new LinkedList <IntervalTree.TreeNode <E, T> >(); todo.Add(node); while (!todo.IsEmpty()) { IntervalTree.TreeNode <E, T> n = todo.Poll(); // Don't search nodes that don't exist if (n == null || n.IsEmpty()) { continue; } // If target is to the right of the rightmost point of any interval // in this node and all children, there won't be any matches. if (target.first.CompareTo(n.maxEnd) > 0) { continue; } // Search left children if (n.left != null) { todo.Add(n.left); } // Check this node if (n.value.GetInterval().Overlaps(target)) { result.Add(n.value); } // If target is to the left of the start of this interval, // then it can't be in any child to the right. if (target.second.CompareTo(n.value.GetInterval().First()) < 0) { continue; } // Otherwise, search right children if (n.right != null) { todo.Add(n.right); } } }
// Balances this tree public virtual IntervalTree.TreeNode <E, T> Balance(IntervalTree.TreeNode <E, T> node) { Stack <IntervalTree.TreeNode <E, T> > todo = new Stack <IntervalTree.TreeNode <E, T> >(); todo.Add(node); IntervalTree.TreeNode <E, T> newRoot = null; while (!todo.IsEmpty()) { IntervalTree.TreeNode <E, T> n = todo.Pop(); // Balance tree between this node // Select median nodes and try to balance the tree int medianAt = n.size / 2; IntervalTree.TreeNode <E, T> median = GetNode(n, medianAt); // Okay, this is going to be our root if (median != null && median != n) { // Yes, there is indeed something to be done RotateUp(median, n); } if (newRoot == null) { newRoot = median; } if (median.left != null) { todo.Push(median.left); } if (median.right != null) { todo.Push(median.right); } } if (newRoot == null) { return(node); } else { return(newRoot); } }
// Moves this node to the left and the right child up and returns the new root public virtual IntervalTree.TreeNode <E, T> LeftRotate(IntervalTree.TreeNode <E, T> oldRoot) { if (oldRoot == null || oldRoot.IsEmpty() || oldRoot.right == null) { return(oldRoot); } IntervalTree.TreeNode <E, T> oldRightLeft = oldRoot.right.left; IntervalTree.TreeNode <E, T> newRoot = oldRoot.right; newRoot.left = oldRoot; oldRoot.right = oldRightLeft; // Adjust parents and such newRoot.parent = oldRoot.parent; newRoot.maxEnd = oldRoot.maxEnd; newRoot.size = oldRoot.size; if (newRoot.parent != null) { if (newRoot.parent.left == oldRoot) { newRoot.parent.left = newRoot; } else { if (newRoot.parent.right == oldRoot) { newRoot.parent.right = newRoot; } else { throw new InvalidOperationException("Old root not a child of it's parent"); } } } oldRoot.parent = newRoot; if (oldRightLeft != null) { oldRightLeft.parent = oldRoot; } Adjust(oldRoot); return(newRoot); }
// Adjust upwards starting at this node until stopAt private void AdjustUpwards(IntervalTree.TreeNode <E, T> node, IntervalTree.TreeNode <E, T> stopAt) { IntervalTree.TreeNode <E, T> n = node; while (n != null && n != stopAt) { int leftSize = (n.left != null) ? n.left.size : 0; int rightSize = (n.right != null) ? n.right.size : 0; n.maxEnd = n.value.GetInterval().GetEnd(); if (n.left != null) { n.maxEnd = Interval.Max(n.maxEnd, n.left.maxEnd); } if (n.right != null) { n.maxEnd = Interval.Max(n.maxEnd, n.right.maxEnd); } n.size = leftSize + 1 + rightSize; if (n == n.parent) { throw new InvalidOperationException("node is same as parent!!!"); } n = n.parent; } }
public static bool Overlaps <E, T>(IntervalTree.TreeNode <E, T> n, E p) where E : IComparable <E> where T : IHasInterval <E> { return(Overlaps(n, Interval.ToInterval(p, p))); }
// Add node to tree - attempting to maintain alpha balance public virtual bool Add(IntervalTree.TreeNode <E, T> node, T target, double alpha) { if (target == null) { return(false); } IntervalTree.TreeNode <E, T> n = node; int depth = 0; int thresholdDepth = (node.size > 10) ? ((int)(-Math.Log(node.size) / Math.Log(alpha) + 1)) : 10; while (n != null) { if (n.value == null) { n.value = target; n.maxEnd = target.GetInterval().GetEnd(); n.size = 1; if (depth > thresholdDepth) { // Do rebalancing IntervalTree.TreeNode <E, T> p = n.parent; while (p != null) { if (p.size > 10 && !IsAlphaBalanced(p, alpha)) { IntervalTree.TreeNode <E, T> newParent = Balance(p); if (p == root) { root = newParent; } break; } p = p.parent; } } return(true); } else { depth++; n.maxEnd = Interval.Max(n.maxEnd, target.GetInterval().GetEnd()); n.size++; if (target.GetInterval().CompareTo(n.value.GetInterval()) <= 0) { // Should go on left if (n.left == null) { n.left = new IntervalTree.TreeNode <E, T>(); n.left.parent = n; } n = n.left; } else { // Should go on right if (n.right == null) { n.right = new IntervalTree.TreeNode <E, T>(); n.right.parent = n; } n = n.right; } } } return(false); }
// Search for all intervals which contain p, starting with the // node "n" and adding matching intervals to the list "result" public static void GetOverlapping <E, T>(IntervalTree.TreeNode <E, T> n, E p, IList <T> result) where E : IComparable <E> where T : IHasInterval <E> { GetOverlapping(n, Interval.ToInterval(p, p), result); }
public virtual bool Remove(IntervalTree.TreeNode <E, T> node, T target) { if (target == null) { return(false); } if (node.value == null) { return(false); } if (target.Equals(node.value)) { int leftSize = (node.left != null) ? node.left.size : 0; int rightSize = (node.right != null) ? node.right.size : 0; if (leftSize == 0) { if (rightSize == 0) { node.Clear(); } else { node.value = node.right.value; node.size = node.right.size; node.maxEnd = node.right.maxEnd; node.left = node.right.left; node.right = node.right.right; if (node.left != null) { node.left.parent = node; } if (node.right != null) { node.right.parent = node; } } } else { if (rightSize == 0) { node.value = node.left.value; node.size = node.left.size; node.maxEnd = node.left.maxEnd; node.left = node.left.left; node.right = node.left.right; if (node.left != null) { node.left.parent = node; } if (node.right != null) { node.right.parent = node; } } else { // Rotate left up node.value = node.left.value; node.size--; node.maxEnd = Interval.Max(node.left.maxEnd, node.right.maxEnd); IntervalTree.TreeNode <E, T> origRight = node.right; node.right = node.left.right; node.left = node.left.left; if (node.left != null) { node.left.parent = node; } if (node.right != null) { node.right.parent = node; } // Attach origRight somewhere... IntervalTree.TreeNode <E, T> rightmost = GetRightmostNode(node); rightmost.right = origRight; if (rightmost.right != null) { rightmost.right.parent = rightmost; // adjust maxEnd and sizes on the right AdjustUpwards(rightmost.right, node); } } } return(true); } else { if (target.GetInterval().CompareTo(node.value.GetInterval()) <= 0) { // Should go on left if (node.left == null) { return(false); } bool res = Remove(node.left, target); if (res) { node.maxEnd = Interval.Max(node.maxEnd, node.left.maxEnd); node.size--; } return(res); } else { // Should go on right if (node.right == null) { return(false); } bool res = Remove(node.right, target); if (res) { node.maxEnd = Interval.Max(node.maxEnd, node.right.maxEnd); node.size--; } return(res); } } }
public virtual bool Add(IntervalTree.TreeNode <E, T> node, T target) { return(Add(node, target, defaultAlpha)); }
private void AdjustUpwards(IntervalTree.TreeNode <E, T> node) { AdjustUpwards(node, null); }
private void Adjust(IntervalTree.TreeNode <E, T> node) { AdjustUpwards(node, node.parent); }
public virtual void Check(IntervalTree.TreeNode <E, T> treeNode) { Stack <IntervalTree.TreeNode <E, T> > todo = new Stack <IntervalTree.TreeNode <E, T> >(); todo.Add(treeNode); while (!todo.IsEmpty()) { IntervalTree.TreeNode <E, T> node = todo.Pop(); if (node == node.parent) { throw new InvalidOperationException("node is same as parent!!!"); } if (node.IsEmpty()) { if (node.left != null) { throw new InvalidOperationException("Empty node shouldn't have left branch"); } if (node.right != null) { throw new InvalidOperationException("Empty node shouldn't have right branch"); } continue; } int leftSize = (node.left != null) ? node.left.size : 0; int rightSize = (node.right != null) ? node.right.size : 0; E leftMax = (node.left != null) ? node.left.maxEnd : null; E rightMax = (node.right != null) ? node.right.maxEnd : null; E maxEnd = node.value.GetInterval().GetEnd(); if (leftMax != null && leftMax.CompareTo(maxEnd) > 0) { maxEnd = leftMax; } if (rightMax != null && rightMax.CompareTo(maxEnd) > 0) { maxEnd = rightMax; } if (!maxEnd.Equals(node.maxEnd)) { throw new InvalidOperationException("max end is not as expected!!!"); } if (node.size != leftSize + rightSize + 1) { throw new InvalidOperationException("node size is not one plus the sum of left and right!!!"); } if (node.left != null) { if (node.left.parent != node) { throw new InvalidOperationException("node left parent is not same as node!!!"); } } if (node.right != null) { if (node.right.parent != node) { throw new InvalidOperationException("node right parent is not same as node!!!"); } } if (node.parent != null) { // Go up parent and make sure we are on correct side IntervalTree.TreeNode <E, T> n = node; while (n != null && n.parent != null) { // Check we are either right or left if (n == n.parent.left) { // Check that node is less than the parent if (node.value != null) { if (node.value.GetInterval().CompareTo(n.parent.value.GetInterval()) > 0) { throw new InvalidOperationException("node is not on the correct side!!!"); } } } else { if (n == n.parent.right) { // Check that node is greater than the parent if (node.value.GetInterval().CompareTo(n.parent.value.GetInterval()) <= 0) { throw new InvalidOperationException("node is not on the correct side!!!"); } } else { throw new InvalidOperationException("node is not parent's left or right child!!!"); } } n = n.parent; } } if (node.left != null) { todo.Add(node.left); } if (node.right != null) { todo.Add(node.right); } } }
public virtual void Balance() { root = Balance(root); }