예제 #1
0
        /// <summary>
        /// Recursively descends down the tree and adds valids results to the resultset
        /// </summary>
        /// <param name="node">subtree to be searched</param>
        /// <param name="val">value to be searched for</param>
        /// <param name="result">current resultset</param>
        private void SearchSubtree(IntervalNode <T> node, T val, List <Interval <T> > result)
        {
            if (node == Sentinel)
            {
                return;
            }

            // Value is higher than any interval in this subtree
            if (val.CompareTo(node.MaxEnd) > 0)
            {
                return;
            }

            if (node.Left != Sentinel)
            {
                SearchSubtree(node.Left, val, result);
            }

            if (node.Interval.Contains(val))
            {
                result.Add(node.Interval);
            }

            if (val.CompareTo(node.Interval.Start) < 0)
            {
                return;
            }

            if (node.Right != Sentinel)
            {
                SearchSubtree(node.Right, val, result);
            }
        }
예제 #2
0
 public IntervalTree()
 {
     this.head         = new IntervalNode <T, D>();
     this.intervalList = new List <Interval <T, D> >();
     this.inSync       = true;
     this.size         = 0;
 }
예제 #3
0
 public IntervalTree()
 {
     Root        = Sentinel;
     Root.Left   = Sentinel;
     Root.Right  = Sentinel;
     Root.Parent = Sentinel;
 }
예제 #4
0
        private IntervalNode <T> FindInterval(IntervalNode <T> tree, Interval <T> i)
        {
            while (tree != Sentinel)
            {
                if (tree.Interval.CompareTo(i) > 0)
                {
                    tree = tree.Left;
                    continue;
                }

                if (tree.Interval.CompareTo(i) < 0)
                {
                    tree = tree.Right;
                    continue;
                }

                if (tree.Interval.CompareTo(i) == 0)
                {
                    return(tree);
                }
            }


            return(Sentinel);
        }
예제 #5
0
        /// <summary>
        /// General left rotation
        /// </summary>
        /// <param name="node">top of rotated subtree</param>
        private void RotateLeft(IntervalNode <T> node)
        {
            var           pivot    = node.Right;
            NodeDirection dir      = node.ParentDirection;
            var           parent   = node.Parent;
            var           tempTree = pivot.Left;

            pivot.Left  = node;
            node.Parent = pivot;
            node.Right  = tempTree;
            if (tempTree != Sentinel)
            {
                tempTree.Parent = node;
            }

            if (dir == NodeDirection.LEFT)
            {
                parent.Right = pivot;
            }
            else if (dir == NodeDirection.RIGHT)
            {
                parent.Left = pivot;
            }
            else
            {
                Root = pivot;
            }

            pivot.Parent = parent;

            pivot.RecalculateMaxEnd();
            node.RecalculateMaxEnd();
        }
예제 #6
0
 public IntervalNode()
 {
     intervals = new OrderedDictionary <Interval <T, D>, List <Interval <T, D> > >();
     center    = default(D);
     leftNode  = null;
     rightNode = null;
 }
예제 #7
0
        private void RemoveNode(IntervalNode <T> node)
        {
            if (node == Sentinel)
            {
                return;
            }

            IntervalNode <T> temp = node;

            if (node.Right != Sentinel && node.Left != Sentinel)
            {
                // Trick when deleting node with both children, switch it with closest in order node
                // swap values and delete the bottom node converting it to other cases

                temp          = node.GetSuccessor();
                node.Interval = temp.Interval;

                node.RecalculateMaxEnd();
                while (node.Parent != Sentinel)
                {
                    node = node.Parent;
                    node.RecalculateMaxEnd();
                }
            }
            node = temp;
            temp = node.Left != Sentinel ? node.Left : node.Right;

            // we will replace node with temp and delete node
            temp.Parent = node.Parent;
            if (node.IsRoot)
            {
                Root = temp; // Set new root
            }
            else
            {
                // Reattach node to parent
                if (node.ParentDirection == NodeDirection.RIGHT)
                {
                    node.Parent.Left = temp;
                }
                else
                {
                    node.Parent.Right = temp;
                }

                IntervalNode <T> maxAux = node.Parent;
                maxAux.RecalculateMaxEnd();
                while (maxAux.Parent != Sentinel)
                {
                    maxAux = maxAux.Parent;
                    maxAux.RecalculateMaxEnd();
                }
            }

            if (node.Color == NodeColor.BLACK)
            {
                RenewConstraintsAfterDelete(temp);
            }
        }
예제 #8
0
 public IntervalTree(List <Interval <T, D> > intervalList)
 {
     this.head         = new IntervalNode <T, D>(intervalList);
     this.intervalList = new List <Interval <T, D> >();
     this.intervalList.AddRange(intervalList);
     this.inSync = true;
     this.size   = intervalList.Count;
 }
예제 #9
0
 /// <summary>
 /// Finds the min.
 /// </summary>
 /// <param name="node">The node.</param>
 /// <returns></returns>
 public static IntervalNode FindMin(IntervalNode node)
 {
     while (node != null && node.Left != null)
     {
         node = node.Left;
     }
     return(node);
 }
예제 #10
0
 /// <summary>
 /// Finds the max.
 /// </summary>
 /// <param name="node">The node.</param>
 /// <returns></returns>
 public static IntervalNode FindMax(IntervalNode node)
 {
     while (node != null && node.Right != null)
     {
         node = node.Right;
     }
     return(node);
 }
예제 #11
0
        /// <summary>
        /// Adds the specified arg.
        /// </summary>
        /// <param name="arg">The arg.</param>
        public void Add(KeyValuePair <IInterval <T>, TypeValue> arg)
        {
            bool wasAdded      = false;
            bool wasSuccessful = false;

            this.Root = IntervalNode.Add(this.Root, arg, ref wasAdded, ref wasSuccessful);
            IntervalNode.ComputeMax(this.Root);
        }
예제 #12
0
 public void Build()
 {
     if (!inSync)
     {
         head   = new IntervalNode <T, D>(intervalList);
         inSync = true;
         size   = intervalList.Count;
     }
 }
예제 #13
0
        /// <summary>
        /// Validates and applies RB-tree constaints to node
        /// </summary>
        /// <param name="node">node to be validated and fixed</param>
        private void RenewConstraintsAfterInsert(IntervalNode <T> node)
        {
            if (node.Parent == Sentinel)
            {
                return;
            }

            if (node.Parent.Color == NodeColor.BLACK)
            {
                return;
            }

            var uncle = node.Uncle;

            if (uncle != Sentinel && uncle.Color == NodeColor.RED)
            {
                node.Parent.Color = uncle.Color = NodeColor.BLACK;

                var gparent = node.GrandParent;
                if (gparent != Sentinel && !gparent.IsRoot)
                {
                    gparent.Color = NodeColor.RED;
                    RenewConstraintsAfterInsert(gparent);
                }
            }
            else
            {
                if (node.ParentDirection == NodeDirection.LEFT && node.Parent.ParentDirection == NodeDirection.RIGHT)
                {
                    RotateLeft(node.Parent);
                    node = node.Left;
                }
                else if (node.ParentDirection == NodeDirection.RIGHT && node.Parent.ParentDirection == NodeDirection.LEFT)
                {
                    RotateRight(node.Parent);
                    node = node.Right;
                }

                node.Parent.Color = NodeColor.BLACK;

                if (node.GrandParent == Sentinel)
                {
                    return;
                }
                node.GrandParent.Color = NodeColor.RED;

                if (node.ParentDirection == NodeDirection.RIGHT)
                {
                    RotateRight(node.GrandParent);
                }
                else
                {
                    RotateLeft(node.GrandParent);
                }
            }
        }
예제 #14
0
        /// <summary>
        /// Insert new interval to interval tree
        /// </summary>
        /// <param name="interval">interval to add</param>
        public void Add(Interval <T> interval)
        {
            var node = new IntervalNode <T>(interval);

            if (Root == Sentinel)
            {
                node.Color = NodeColor.BLACK;
                Root       = node;
            }
            else
            {
                InsertInterval(interval, Root);
            }
        }
예제 #15
0
        public IntervalNode(List <Interval <T, D> > intervalList)
        {
            intervals = new OrderedDictionary <Interval <T, D>, List <Interval <T, D> > >();

            var endpoints = new OrderedSet <D>();

            foreach (var interval in intervalList)
            {
                endpoints.Add(interval.Start);
                endpoints.Add(interval.End);
            }

            Nullable <D> median = GetMedian(endpoints);

            center = median.GetValueOrDefault();

            List <Interval <T, D> > left  = new List <Interval <T, D> >();
            List <Interval <T, D> > right = new List <Interval <T, D> >();

            foreach (Interval <T, D> interval in intervalList)
            {
                if (interval.End.CompareTo(center) < 0)
                {
                    left.Add(interval);
                }
                else if (interval.Start.CompareTo(center) > 0)
                {
                    right.Add(interval);
                }
                else
                {
                    List <Interval <T, D> > posting;
                    if (!intervals.TryGetValue(interval, out posting))
                    {
                        posting = new List <Interval <T, D> >();
                        intervals.Add(interval, posting);
                    }
                    posting.Add(interval);
                }
            }

            if (left.Count > 0)
            {
                leftNode = new IntervalNode <T, D>(left);
            }
            if (right.Count > 0)
            {
                rightNode = new IntervalNode <T, D>(right);
            }
        }
예제 #16
0
        /// <summary>
        /// Deletes the interval starting at x.
        /// </summary>
        /// <param name="arg">The arg.</param>
        public void Delete(IInterval <T> arg)
        {
            if (Root != null)
            {
                bool wasDeleted    = false;
                bool wasSuccessful = false;

                Root = IntervalNode.Delete(Root, arg, ref wasDeleted, ref wasSuccessful);
                if (this.Root != null)
                {
                    IntervalNode.ComputeMax(this.Root);
                }
            }
        }
예제 #17
0
        /// <summary>
        /// Recursively descends to the correct spot for interval insertion in the tree
        /// When a free spot is found for the node, it is attached and tree state is validated
        /// </summary>
        /// <param name="interval">interval to be added</param>
        /// <param name="currentNode">subtree accessed in recursion</param>
        private void InsertInterval(Interval <T> interval, IntervalNode <T> currentNode)
        {
            IntervalNode <T> addedNode = Sentinel;

            if (interval.CompareTo(currentNode.Interval) < 0)
            {
                if (currentNode.Left == Sentinel)
                {
                    addedNode        = new IntervalNode <T>(interval);
                    addedNode.Color  = NodeColor.RED;
                    currentNode.Left = addedNode;
                    addedNode.Parent = currentNode;
                }
                else
                {
                    InsertInterval(interval, currentNode.Left);
                    return;
                }
            }
            else if (interval.CompareTo(currentNode.Interval) > 0)
            {
                if (currentNode.Right == Sentinel)
                {
                    addedNode         = new IntervalNode <T>(interval);
                    addedNode.Color   = NodeColor.RED;
                    currentNode.Right = addedNode;
                    addedNode.Parent  = currentNode;
                }
                else
                {
                    InsertInterval(interval, currentNode.Right);
                    return;
                }
            }
            else
            {
                return;
            }

            addedNode.Parent.RecalculateMaxEnd();

            RenewConstraintsAfterInsert(addedNode);

            Root.Color = NodeColor.BLACK;
        }
예제 #18
0
        private String NodeString(IntervalNode <T, D> node, int level)
        {
            if (node == null)
            {
                return("");
            }

            var sb = new StringBuilder();

            for (int i = 0; i < level; i++)
            {
                sb.Append("\t");
            }
            sb.Append(node + "\n");
            sb.Append(NodeString(node.Left, level + 1));
            sb.Append(NodeString(node.Right, level + 1));
            return(sb.ToString());
        }
예제 #19
0
 /// <summary>
 /// Computes the max.
 /// </summary>
 /// <param name="node">The node.</param>
 public static void ComputeMax(IntervalNode node)
 {
     if (node.Left == null && node.Right == null)
     {
         node.Max = node.MaxRange;
     }
     else if (node.Left == null)
     {
         node.Max = Max(node.MaxRange, node.Right.Max);
     }
     else if (node.Right == null)
     {
         node.Max = Max(node.MaxRange, node.Left.Max);
     }
     else
     {
         node.Max = Max(node.MaxRange, Max(node.Left.Max, node.Right.Max));
     }
 }
예제 #20
0
 /// <summary>
 /// Searches the specified subtree.
 /// </summary>
 /// <param name="subtree">The subtree.</param>
 /// <param name="data">The data.</param>
 /// <returns></returns>
 public static IntervalNode Search(IntervalNode subtree, IInterval <T> data)
 {
     if (subtree != null)
     {
         if (data.Start.CompareTo(subtree.Data.Key.Start) < 0)
         {
             return(Search(subtree.Left, data));
         }
         else if (data.Start.CompareTo(subtree.Data.Key.Start) > 0)
         {
             return(Search(subtree.Right, data));
         }
         else
         {
             return(subtree);
         }
     }
     else
     {
         return(null);
     }
 }
예제 #21
0
        private void SearchSubtree(IntervalNode <T> node, Interval <T> i, List <Interval <T> > result)
        {
            if (node == Sentinel)
            {
                return;
            }

            if (node.Left != Sentinel)
            {
                SearchSubtree(node.Left, i, result);
            }

            if (i.Overlaps(node.Interval))
            {
                result.Add(node.Interval);
            }

            // Interval start is greater than largest endpoint in this subtree
            if (node.Right != Sentinel && i.Start.CompareTo(node.MaxEnd) <= 0)
            {
                SearchSubtree(node.Right, i, result);
            }
        }
예제 #22
0
        private IEnumerable <Interval <T> > InOrderWalk(IntervalNode <T> node)
        {
            if (node.Left != Sentinel)
            {
                foreach (Interval <T> val in InOrderWalk(node.Left))
                {
                    yield return(val);
                }
            }

            if (node != Sentinel)
            {
                yield return(node.Interval);
            }

            if (node.Right != Sentinel)
            {
                foreach (Interval <T> val in InOrderWalk(node.Right))
                {
                    yield return(val);
                }
            }
        }
예제 #23
0
            /// <summary>
            /// Rotates lefts this instance.
            /// Assumes that this.Right != null
            /// </summary>
            /// <returns></returns>
            private IntervalNode RotateLeft()
            {
                var right = this.Right;

                Debug.Assert(this.Right != null);

                this.Right = right.Left;
                ComputeMax(this);

#if TREE_WITH_PARENT_POINTERS
                var parent = this.Parent;
                if (right.Left != null)
                {
                    right.Left.Parent = this;
                }
#endif
                right.Left = this;
                ComputeMax(right);

#if TREE_WITH_PARENT_POINTERS
                this.Parent = right;
                if (parent != null)
                {
                    if (parent.Left == this)
                    {
                        parent.Left = right;
                    }
                    else
                    {
                        parent.Right = right;
                    }
                }
                right.Parent = parent;
#endif

                return(right);
            }
예제 #24
0
 public int CompareTo(IntervalNode <T> other)
 {
     return(Interval.CompareTo(other.Interval));
 }
예제 #25
0
            /// <summary>
            /// Returns all intervals beginning at the specified start value
            /// </summary>
            /// <param name="subtree">The subtree.</param>
            /// <param name="data">The data.</param>
            /// <returns></returns>
            public static List <KeyValuePair <IInterval <T>, TypeValue> > GetIntervalsStartingAt(IntervalNode subtree, T start)
            {
                if (subtree != null)
                {
                    if (start.CompareTo(subtree.Data.Key.Start) < 0)
                    {
                        return(GetIntervalsStartingAt(subtree.Left, start));
                    }
                    else if (start.CompareTo(subtree.Data.Key.Start) > 0)
                    {
                        return(GetIntervalsStartingAt(subtree.Right, start));
                    }
                    else
                    {
                        var result = new List <KeyValuePair <IInterval <T>, TypeValue> >();
                        result.Add(subtree.Data);

                        if (subtree.Range != null)
                        {
                            foreach (var value in subtree.Range)
                            {
                                var kInterval = new Interval <T>(start, value.Key);
                                result.Add(new KeyValuePair <IInterval <T>, TypeValue>(kInterval, value.Value));
                            }
                        }

                        return(result);
                    }
                }
                else
                {
                    return(null);
                }
            }
예제 #26
0
            /// <summary>
            /// Deletes the specified node.
            /// </summary>
            /// <param name="node">The node.</param>
            /// <param name="arg">The arg.</param>
            /// <returns></returns>
            public static IntervalNode Delete(IntervalNode node, IInterval <T> arg, ref bool wasDeleted, ref bool wasSuccessful)
            {
                int cmp = arg.Start.CompareTo(node.Data.Key.Start);

                if (cmp < 0)
                {
                    if (node.Left != null)
                    {
                        node.Left = Delete(node.Left, arg, ref wasDeleted, ref wasSuccessful);

                        if (wasDeleted)
                        {
                            node.Balance++;
                        }
                    }
                }
                else if (cmp == 0)
                {
                    int position = -1;

                    // find the exact interval to delete based on the Y value.. consider changing this code
                    if (arg.End.CompareTo(node.Data.Key.End) == 0)
                    {
                        position = 0;
                    }
                    else
                    {
                        if (node.Range != null && node.Range.Count > 0)
                        {
                            for (int k = 0; k < node.Range.Count; k++)
                            {
                                if (arg.End.CompareTo(node.Range[k].Key) == 0)
                                {
                                    position = k + 1;
                                }
                            }
                        }
                    }

                    // couldn't find the interval in the tree, throw an exception
                    if (position == -1)
                    {
                        throw new ArgumentOutOfRangeException("arg", "cannot delete the specified interval. invalid argument.");
                    }

                    if (position > 0)
                    {
                        // we're counting the value stored in the node.Data.Value as position 0, all values stored in Range represent position + 1, position + 2, ...etc
                        if (node.Range != null && position - 1 < node.Range.Count)
                        {
                            node.Range.RemoveAt(position - 1);

                            if (node.Range.Count == 0)
                            {
                                node.Range = null;
                            }

                            wasSuccessful = true;
                        }
                    }
                    else if (position == 0 && node.Range != null && node.Range.Count > 0)
                    {
                        node.Data = new KeyValuePair <IInterval <T>, TypeValue>(
                            new Interval <T>(node.Data.Key.Start, node.Range[0].Key),
                            node.Range[0].Value);
                        node.Range.RemoveAt(0);
                        if (node.Range.Count == 0)
                        {
                            node.Range = null;
                        }

                        wasSuccessful = true;
                    }
                    else
                    {
                        if (node.Left != null && node.Right != null)
                        {
                            var min = FindMin(node.Right);

                            var data  = node.Data;
                            var range = node.Range;

                            node.Data  = min.Data;
                            node.Range = min.Range;

                            min.Data  = data;
                            min.Range = range;

                            wasDeleted = false;
                            node.Right = Delete(node.Right, data.Key, ref wasDeleted, ref wasSuccessful);

                            if (wasDeleted)
                            {
                                node.Balance--;
                            }
                        }
                        else if (node.Left == null)
                        {
                            wasDeleted    = true;
                            wasSuccessful = true;
                            return(node.Right);
                        }
                        else
                        {
                            wasDeleted    = true;
                            wasSuccessful = true;
                            return(node.Left);
                        }
                    }
                }
                else
                {
                    if (node.Right != null)
                    {
                        node.Right = Delete(node.Right, arg, ref wasDeleted, ref wasSuccessful);
                        if (wasDeleted)
                        {
                            node.Balance--;
                        }
                    }
                }
                ComputeMax(node);

                if (wasDeleted)
                {
                    if (node.Balance == 1 || node.Balance == -1)
                    {
                        wasDeleted = false;
                        return(node);
                    }

                    else if (node.Balance == -2)
                    {
                        if (node.Left.Balance == 1)
                        {
                            int leftRightBalance = node.Left.Right.Balance;

                            node.Left = node.Left.RotateLeft();
                            node      = node.RotateRight();

                            node.Balance       = 0;
                            node.Left.Balance  = (leftRightBalance == 1) ? -1 : 0;
                            node.Right.Balance = (leftRightBalance == -1) ? 1 : 0;
                        }
                        else if (node.Left.Balance == -1)
                        {
                            node               = node.RotateRight();
                            node.Balance       = 0;
                            node.Right.Balance = 0;
                        }
                        else if (node.Left.Balance == 0)
                        {
                            node               = node.RotateRight();
                            node.Balance       = 1;
                            node.Right.Balance = -1;

                            wasDeleted = false;
                        }
                    }

                    else if (node.Balance == 2)
                    {
                        if (node.Right.Balance == -1)
                        {
                            int rightLeftBalance = node.Right.Left.Balance;

                            node.Right = node.Right.RotateRight();
                            node       = node.RotateLeft();

                            node.Balance       = 0;
                            node.Left.Balance  = (rightLeftBalance == 1) ? -1 : 0;
                            node.Right.Balance = (rightLeftBalance == -1) ? 1 : 0;
                        }
                        else if (node.Right.Balance == 1)
                        {
                            node              = node.RotateLeft();
                            node.Balance      = 0;
                            node.Left.Balance = 0;
                        }
                        else if (node.Right.Balance == 0)
                        {
                            node              = node.RotateLeft();
                            node.Balance      = -1;
                            node.Left.Balance = 1;

                            wasDeleted = false;
                        }
                    }
                }
                return(node);
            }
예제 #27
0
        /// <summary>
        /// Ensures constraints still apply after node deletion
        ///
        ///  - made with the help of algorithm from Cormen et Al. Introduction to Algorithms 2nd ed.
        /// </summary>
        /// <param name="node"></param>
        private void RenewConstraintsAfterDelete(IntervalNode <T> node)
        {
            // Need to bubble up and fix
            while (node != Root && node.Color == NodeColor.BLACK)
            {
                if (node.ParentDirection == NodeDirection.RIGHT)
                {
                    IntervalNode <T> aux = node.Parent.Right;
                    if (aux.Color == NodeColor.RED)
                    {
                        aux.Color         = NodeColor.BLACK;
                        node.Parent.Color = NodeColor.RED;
                        RotateLeft(node.Parent);
                        aux = node.Parent.Right;
                    }

                    if (aux.Left.Color == NodeColor.BLACK && aux.Right.Color == NodeColor.BLACK)
                    {
                        aux.Color = NodeColor.RED;
                        node      = node.Parent;
                    }
                    else
                    {
                        if (aux.Right.Color == NodeColor.BLACK)
                        {
                            aux.Left.Color = NodeColor.BLACK;
                            aux.Color      = NodeColor.RED;
                            RotateRight(aux);
                            aux = node.Parent.Right;
                        }

                        aux.Color         = node.Parent.Color;
                        node.Parent.Color = NodeColor.BLACK;
                        aux.Right.Color   = NodeColor.BLACK;
                        RotateLeft(node.Parent);
                        node = Root;
                    }
                }
                else
                {
                    IntervalNode <T> aux = node.Parent.Left;
                    if (aux.Color == NodeColor.RED)
                    {
                        aux.Color         = NodeColor.BLACK;
                        node.Parent.Color = NodeColor.RED;
                        RotateRight(node.Parent);
                        aux = node.Parent.Left;
                    }

                    if (aux.Left.Color == NodeColor.BLACK && aux.Right.Color == NodeColor.BLACK)
                    {
                        aux.Color = NodeColor.RED;
                        node      = node.Parent;
                    }
                    else
                    {
                        if (aux.Left.Color == NodeColor.BLACK)
                        {
                            aux.Right.Color = NodeColor.BLACK;
                            aux.Color       = NodeColor.RED;
                            RotateLeft(aux);
                            aux = node.Parent.Left;
                        }

                        aux.Color         = node.Parent.Color;
                        node.Parent.Color = NodeColor.BLACK;
                        aux.Left.Color    = NodeColor.BLACK;
                        RotateRight(node.Parent);
                        node = Root;
                    }
                }
            }

            node.Color = NodeColor.BLACK;
        }
예제 #28
0
 /// <summary>
 /// Searches the specified arg.
 /// </summary>
 /// <param name="arg">The arg.</param>
 /// <returns></returns>
 public List <KeyValuePair <IInterval <T>, TypeValue> > GetIntervalsStartingAt(T arg)
 {
     return(IntervalNode.GetIntervalsStartingAt(Root, arg));
 }
예제 #29
0
            /// <summary>
            /// Adds the specified elem.
            /// </summary>
            /// <param name="elem">The elem.</param>
            /// <param name="data">The data.</param>
            /// <returns></returns>
            public static IntervalNode Add(
                IntervalNode elem,
                KeyValuePair <IInterval <T>, TypeValue> data,
                ref bool wasAdded,
                ref bool wasSuccessful)
            {
                if (elem == null)
                {
                    elem = new IntervalNode {
                        Data = data, Left = null, Right = null, Balance = 0, Max = data.Key.End
                    };
                    wasAdded      = true;
                    wasSuccessful = true;
                }
                else
                {
                    if (data.Key.Start.CompareTo(elem.Data.Key.Start) < 0)
                    {
                        elem.Left = Add(elem.Left, data, ref wasAdded, ref wasSuccessful);
                        if (wasAdded)
                        {
                            elem.Balance--;

                            if (elem.Balance == 0)
                            {
                                wasAdded = false;
                            }
                        }

#if TREE_WITH_PARENT_POINTERS
                        elem.Left.Parent = elem;
#endif

                        if (elem.Balance == -2)
                        {
                            if (elem.Left.Balance == 1)
                            {
                                int elemLeftRightBalance = elem.Left.Right.Balance;

                                elem.Left = elem.Left.RotateLeft();
                                elem      = elem.RotateRight();

                                elem.Balance       = 0;
                                elem.Left.Balance  = elemLeftRightBalance == 1 ? -1 : 0;
                                elem.Right.Balance = elemLeftRightBalance == -1 ? 1 : 0;
                            }

                            else if (elem.Left.Balance == -1)
                            {
                                elem               = elem.RotateRight();
                                elem.Balance       = 0;
                                elem.Right.Balance = 0;
                            }
                            wasAdded = false;
                        }
                    }
                    else if (data.Key.Start.CompareTo(elem.Data.Key.Start) > 0)
                    {
                        elem.Right = Add(elem.Right, data, ref wasAdded, ref wasSuccessful);
                        if (wasAdded)
                        {
                            elem.Balance++;
                            if (elem.Balance == 0)
                            {
                                wasAdded = false;
                            }
                        }

#if TREE_WITH_PARENT_POINTERS
                        elem.Right.Parent = elem;
#endif

                        if (elem.Balance == 2)
                        {
                            if (elem.Right.Balance == -1)
                            {
                                int elemRightLeftBalance = elem.Right.Left.Balance;

                                elem.Right = elem.Right.RotateRight();
                                elem       = elem.RotateLeft();

                                elem.Balance       = 0;
                                elem.Left.Balance  = elemRightLeftBalance == 1 ? -1 : 0;
                                elem.Right.Balance = elemRightLeftBalance == -1 ? 1 : 0;
                            }

                            else if (elem.Right.Balance == 1)
                            {
                                elem = elem.RotateLeft();

                                elem.Balance      = 0;
                                elem.Left.Balance = 0;
                            }
                            wasAdded = false;
                        }
                    }

                    else
                    {
                        // we allow multiple values per key
                        if (elem.Range == null)
                        {
                            elem.Range = new List <KeyValuePair <T, TypeValue> >();
                        }

                        //always store the max Y value in the node.Data itself .. store the Range list in decreasing order
                        if (data.Key.End.CompareTo(elem.Data.Key.End) > 0)
                        {
                            elem.Range.Insert(0, new KeyValuePair <T, TypeValue>(elem.Data.Key.End, elem.Data.Value));
                            elem.Data = data;
                        }
                        else
                        {
                            for (int i = 0; i < elem.Range.Count; i++)
                            {
                                if (data.Key.End.CompareTo(elem.Range[i].Key) >= 0)
                                {
                                    elem.Range.Insert(i, new KeyValuePair <T, TypeValue>(data.Key.End, data.Value));

                                    break;
                                }
                            }
                        }

                        wasSuccessful = true;
                    }
                }
                ComputeMax(elem);
                return(elem);
            }