Exemplo n.º 1
0
        private bool ContainsEdgeInclusive(T value, int start, int length)
        {
            var otherStart = start;
            var otherEnd   = start + length;

            var thisEnd   = GetEnd(value, Introspector);
            var thisStart = Introspector.GetStart(value);

            return(thisStart <= otherStart && otherEnd <= thisEnd);
        }
Exemplo n.º 2
0
        private T GetSmallestContainingIntervalWorker(int start, int length, Func <T, int, int, bool> predicate)
        {
            var result = default(T);

            if (root == null || MaxEndValue(root) < start)
            {
                return(result);
            }

            var end = start + length;

            // * our interval tree is a binary tree that is ordered by a start position.
            //
            // this method works by
            // 1. find a sub tree that has biggest "start" position that is smaller than given "start" by going down right side of a tree
            // 2. once it encounters a right sub tree that it can't go down anymore, move down to left sub tree once and try #1 again
            // 3. once it gets to the position where it can't find any smaller span (both left and
            //    right sub tree doesn't contain given span) start to check whether current node
            //    contains the given "span"
            // 4. move up the spin until it finds one that contains the "span" which should be smallest span that contains the given "span"
            // 5. if it is going up from right side, it make sure to check left side of tree first.
            using (var pooledObject = SharedPools.Default <Stack <Node> >().GetPooledObject())
            {
                var spineNodes = pooledObject.Object;

                spineNodes.Push(root);
                while (spineNodes.Count > 0)
                {
                    var currentNode = spineNodes.Peek();

                    // only goes to right if right tree contains given span
                    if (Introspector.GetStart(currentNode.Value) <= start)
                    {
                        var right = currentNode.Right;
                        if (right != null && end < MaxEndValue(right))
                        {
                            spineNodes.Push(right);
                            continue;
                        }
                    }

                    // right side, sub tree doesn't contain the given span, put current node on
                    // stack, and move down to left sub tree
                    var left = currentNode.Left;
                    if (left != null && end <= MaxEndValue(left))
                    {
                        spineNodes.Push(left);
                        continue;
                    }

                    // we reached the point, where we can't go down anymore.
                    // now, go back up to find best answer
                    while (spineNodes.Count > 0)
                    {
                        currentNode = spineNodes.Pop();

                        // check whether current node meets condition
                        if (predicate(currentNode.Value, start, length))
                        {
                            // hold onto best answer
                            if (EqualityComparer <T> .Default.Equals(result, default) ||
                                (Introspector.GetStart(result) <= Introspector.GetStart(currentNode.Value) &&
                                 Introspector.GetLength(currentNode.Value) < Introspector.GetLength(result)))
                            {
                                result = currentNode.Value;
                            }
                        }

                        // there is no parent, result we currently have is the best answer
                        if (spineNodes.Count == 0)
                        {
                            return(result);
                        }

                        var parentNode = spineNodes.Peek();

                        // if we are under left side of parent node
                        if (parentNode.Left == currentNode)
                        {
                            // go one level up again
                            continue;
                        }

                        // okay, we are under right side of parent node
                        if (parentNode.Right == currentNode)
                        {
                            // try left side of parent node if it can have better answer
                            if (parentNode.Left != null && end <= MaxEndValue(parentNode.Left))
                            {
                                // right side tree doesn't have any answer or if the right side has
                                // an answer but left side can have better answer then try left side
                                if (EqualityComparer <T> .Default.Equals(result, default) ||
                                    Introspector.GetStart(parentNode.Value) == Introspector.GetStart(currentNode.Value))
                                {
                                    // put left as new root, and break out inner loop
                                    spineNodes.Push(parentNode.Left);
                                    break;
                                }
                            }

                            // no left side, go one more level up
                            continue;
                        }
                    }
                }

                return(result);
            }
        }