Exemple #1
0
        /// <summary>
        /// Moves to the next node
        /// </summary>
        /// <returns>True if the move to the next node was successful; otherwise false</returns>
        public bool MoveNext()
        {
            if (this.current == null)
            {
                this.current = this.avlTree.GetFirstNode();
            }
            else
            {
                this.current = this.current.GetNextNode();
            }

            // Should check for an empty tree too :-)
            if (this.current == null)
            {
                return(false);
            }

            return(true);
        }
Exemple #2
0
        /// <summary>
        /// Replace a node
        /// </summary>
        /// <param name="target">The node to replace</param>
        /// <param name="source">The replacing node</param>
        private static void Replace(AvlNode <T> target, AvlNode <T> source)
        {
            AvlNode <T> left  = source.Left;
            AvlNode <T> right = source.Right;

            target.Balance = source.Balance;
            target.Item    = source.Item;
            target.Left    = left;
            target.Right   = right;

            if (left != null)
            {
                left.Parent = target;
            }

            if (right != null)
            {
                right.Parent = target;
            }
        }
Exemple #3
0
        /// <summary>
        /// Find child max height
        /// </summary>
        /// <param name="node">A node in the tree</param>
        /// <returns>The height</returns>
        private int RecursiveGetChildMaxHeight(AvlNode <T> node)
        {
            if (node == null)
            {
                return(0);
            }

            int leftHeight = 0;

            if (node.Left != null)
            {
                leftHeight = this.RecursiveGetChildMaxHeight(node.Left);
            }

            int rightHeight = 0;

            if (node.Right != null)
            {
                rightHeight = this.RecursiveGetChildMaxHeight(node.Right);
            }

            return(1 + Math.Max(leftHeight, rightHeight));
        }
Exemple #4
0
        /// <summary>
        /// Gets a node with the provided item
        /// </summary>
        /// <param name="item">An item to find</param>
        /// <returns>The node with that item</returns>
        protected AvlNode <T> GetNode(T item)
        {
            AvlNode <T> node = this.root;

            while (node != null)
            {
                int compareResult = this.comparer.Compare(item, node.Item);
                if (compareResult < 0)
                {
                    node = node.Left;
                }
                else if (compareResult > 0)
                {
                    node = node.Right;
                }
                else
                {
                    return(node);
                }
            }

            return(null);
        }
Exemple #5
0
        /// <summary>
        /// Removes a node
        /// </summary>
        /// <param name="item">item to remove</param>
        /// <returns>True if successful; otherwise false</returns>
        public virtual bool Remove(T item)
        {
            AvlNode <T> node = this.root;

            while (node != null)
            {
                if (this.comparer.Compare(item, node.Item) < 0)
                {
                    node = node.Left;
                }
                else if (this.comparer.Compare(item, node.Item) > 0)
                {
                    node = node.Right;
                }
                else
                {
                    this.RemoveNode(node);
                    return(true);
                }
            }

            return(false);
        }
Exemple #6
0
        /// <summary>
        /// Gets a value indicating whether the tree contains an item
        /// </summary>
        /// <param name="item">The item to find</param>
        /// <returns>True if the item is found; otherwise false;</returns>
        public bool Contains(T item)
        {
            AvlNode <T> node = this.root;

            while (node != null)
            {
                int compareResult = this.comparer.Compare(item, node.Item);
                if (compareResult < 0)
                {
                    node = node.Left;
                }
                else if (compareResult > 0)
                {
                    node = node.Right;
                }
                else
                {
                    return(true);
                }
            }

            return(false);
        }
        /// <summary>
        /// Iterate over each points to see if we can add it has a ConvexHull point.
        /// It is specific by Quadrant to improve efficiency.
        /// </summary>
        /// <param name="point">a point</param>
        //// [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal override void ProcessPoint(ref MutablePoint point)
        {
            this.CurrentNode = this.Root;
            AvlNode <MutablePoint> currentPrevious = null;
            AvlNode <MutablePoint> currentNext     = null;

            while (this.CurrentNode != null)
            {
                var insertionSide = Side.Unknown;
                if (point.X > this.CurrentNode.Item.X)
                {
                    if (this.CurrentNode.Left != null)
                    {
                        this.CurrentNode = this.CurrentNode.Left;
                        continue;
                    }

                    currentPrevious = this.CurrentNode.GetPreviousNode();
                    if (CanQuickReject(ref point, ref currentPrevious.Item))
                    {
                        return;
                    }

                    if (!this.IsPointToTheRightOfOthers(currentPrevious.Item, this.CurrentNode.Item, point))
                    {
                        return;
                    }

                    // Ensure to have no duplicate
                    if (this.CurrentNode.Item == point)
                    {
                        return;
                    }

                    insertionSide = Side.Left;
                }
                else if (point.X < this.CurrentNode.Item.X)
                {
                    if (this.CurrentNode.Right != null)
                    {
                        this.CurrentNode = this.CurrentNode.Right;
                        continue;
                    }

                    currentNext = this.CurrentNode.GetNextNode();
                    if (CanQuickReject(ref point, ref currentNext.Item))
                    {
                        return;
                    }

                    if (!this.IsPointToTheRightOfOthers(this.CurrentNode.Item, currentNext.Item, point))
                    {
                        return;
                    }

                    // Ensure to have no duplicate
                    if (this.CurrentNode.Item == point)
                    {
                        continue;
                    }

                    insertionSide = Side.Right;
                }
                else
                {
                    if (point.Y <= this.CurrentNode.Item.Y)
                    {
                        return; // invalid point
                    }

                    // Replace CurrentNode point with point
                    this.CurrentNode.Item = point;
                    this.InvalidateNeighbors(this.CurrentNode.GetPreviousNode(), this.CurrentNode, this.CurrentNode.GetNextNode());
                    return;
                }

                // We should insert the point
                // Try to optimize and verify if can replace a node instead insertion to minimize tree balancing
                if (insertionSide == Side.Right)
                {
                    currentPrevious = this.CurrentNode.GetPreviousNode();
                    if (currentPrevious != null && !this.IsPointToTheRightOfOthers(currentPrevious.Item, point, this.CurrentNode.Item))
                    {
                        this.CurrentNode.Item = point;
                        this.InvalidateNeighbors(currentPrevious, this.CurrentNode, currentNext);
                        return;
                    }

                    var nextNext = currentNext.GetNextNode();
                    if (nextNext != null && !this.IsPointToTheRightOfOthers(point, nextNext.Item, currentNext.Item))
                    {
                        currentNext.Item = point;
                        this.InvalidateNeighbors(null, currentNext, nextNext);
                        return;
                    }
                }
                else
                {
                    // Left
                    currentNext = this.CurrentNode.GetNextNode();
                    if (currentNext != null && !this.IsPointToTheRightOfOthers(point, currentNext.Item, this.CurrentNode.Item))
                    {
                        this.CurrentNode.Item = point;
                        this.InvalidateNeighbors(currentPrevious, this.CurrentNode, currentNext);
                        return;
                    }

                    var previousPrevious = currentPrevious.GetPreviousNode();
                    if (previousPrevious != null && !this.IsPointToTheRightOfOthers(previousPrevious.Item, point, currentPrevious.Item))
                    {
                        currentPrevious.Item = point;
                        this.InvalidateNeighbors(previousPrevious, currentPrevious, null);
                        return;
                    }
                }

                // Should insert but no invalidation is required. (That's why we need to insert... can't replace an adjacent neighbor)
                AvlNode <MutablePoint> newNode = new AvlNode <MutablePoint>();
                if (insertionSide == Side.Right)
                {
                    newNode.Parent         = this.CurrentNode;
                    newNode.Item           = point;
                    this.CurrentNode.Right = newNode;
                    this.AddBalance(newNode.Parent, -1);
                }
                else
                {
                    // Left
                    newNode.Parent        = this.CurrentNode;
                    newNode.Item          = point;
                    this.CurrentNode.Left = newNode;
                    this.AddBalance(newNode.Parent, 1);
                }

                return;
            }
        }
Exemple #8
0
        /// <summary>
        /// Removes a node
        /// </summary>
        /// <param name="node">node to remove</param>
        protected void RemoveNode(AvlNode <T> node)
        {
            this.count--;

            AvlNode <T> left  = node.Left;
            AvlNode <T> right = node.Right;

            if (left == null)
            {
                if (right == null)
                {
                    if (node == this.root)
                    {
                        this.root = null;
                    }
                    else
                    {
                        if (node.Parent.Left == node)
                        {
                            node.Parent.Left = null;

                            this.RemoveBalance(node.Parent, -1);
                        }
                        else if (node.Parent.Right == node)
                        {
                            node.Parent.Right = null;

                            this.RemoveBalance(node.Parent, 1);
                        }
                    }
                }
                else
                {
                    Replace(node, right);

                    this.RemoveBalance(node, 0);
                }
            }
            else if (right == null)
            {
                Replace(node, left);

                this.RemoveBalance(node, 0);
            }
            else
            {
                AvlNode <T> successor = right;

                if (successor.Left == null)
                {
                    AvlNode <T> parent = node.Parent;

                    successor.Parent  = parent;
                    successor.Left    = left;
                    successor.Balance = node.Balance;

                    left.Parent = successor;

                    if (node == this.root)
                    {
                        this.root = successor;
                    }
                    else
                    {
                        if (parent.Left == node)
                        {
                            parent.Left = successor;
                        }
                        else
                        {
                            parent.Right = successor;
                        }
                    }

                    this.RemoveBalance(successor, 1);
                }
                else
                {
                    while (successor.Left != null)
                    {
                        successor = successor.Left;
                    }

                    AvlNode <T> parent          = node.Parent;
                    AvlNode <T> successorParent = successor.Parent;
                    AvlNode <T> successorRight  = successor.Right;

                    if (successorParent.Left == successor)
                    {
                        successorParent.Left = successorRight;
                    }
                    else
                    {
                        successorParent.Right = successorRight;
                    }

                    if (successorRight != null)
                    {
                        successorRight.Parent = successorParent;
                    }

                    successor.Parent  = parent;
                    successor.Left    = left;
                    successor.Balance = node.Balance;
                    successor.Right   = right;
                    right.Parent      = successor;

                    left.Parent = successor;

                    if (node == this.root)
                    {
                        this.root = successor;
                    }
                    else
                    {
                        if (parent.Left == node)
                        {
                            parent.Left = successor;
                        }
                        else
                        {
                            parent.Right = successor;
                        }
                    }

                    this.RemoveBalance(successorParent, -1);
                }
            }
        }
Exemple #9
0
        /// <summary>
        /// Copies to an array
        /// </summary>
        /// <param name="array">The array to copy to</param>
        /// <param name="index">start point</param>
        /// <param name="count">number of items to copy</param>
        public void CopyTo(T[] array, int index, int count)
        {
            if (array == null)
            {
                throw new ArgumentNullException("'array' can't be null");
            }

            if (index < 0)
            {
                throw new ArgumentException("'index' can't be null");
            }

            if (count < 0)
            {
                throw new ArgumentOutOfRangeException("'count' should be greater or equal to 0");
            }

            if (index > array.Length || count > array.Length - index)
            {
                throw new ArgumentException("The array size is not big enough to get all items");
            }

            if (count == 0)
            {
                return;
            }

            int indexIter  = 0;
            int indexArray = 0;

            AvlNode <T> current = this.GetFirstNode();

            while (current.GetNextNode() != null)
            {
                if (indexIter >= index)
                {
                    array[indexArray] = current.Item;
                    indexArray++;
                    count--;
                    if (count == 0)
                    {
                        return;
                    }
                }

                indexIter++;
            }

            /*
             * foreach (AvlNode<T> node in this.Nodes())
             * {
             *  if (indexIter >= index)
             *  {
             *      array[indexArray] = node.Item;
             *      indexArray++;
             *      count--;
             *      if (count == 0)
             *      {
             *          return;
             *      }
             *  }
             *
             *  indexIter++;
             * }*/
        }
Exemple #10
0
 /// <inheritdoc/>
 public void Clear()
 {
     this.root  = null;
     this.count = 0;
 }
Exemple #11
0
 /// <summary>
 /// Resets the enumerator
 /// </summary>
 public void Reset()
 {
     this.current = null;
 }
Exemple #12
0
        protected void InvalidateNeighbors(AvlNode <MutablePoint> pointPrevious, AvlNode <MutablePoint> pointNew, AvlNode <MutablePoint> pointNext)
        {
            bool invalidPoint;

            if (pointPrevious != null)
            {
                AvlNode <MutablePoint> previousPrevious = pointPrevious.GetPreviousNode();
                for (; ;)
                {
                    if (previousPrevious == null)
                    {
                        break;
                    }

                    invalidPoint = !this.IsPointToTheRightOfOthers(previousPrevious.Item, pointNew.Item, pointPrevious.Item);
                    if (!invalidPoint)
                    {
                        break;
                    }

                    MutablePoint pointPrevPrev = previousPrevious.Item;
                    this.RemoveNode(pointPrevious);
                    pointPrevious    = this.GetNode(pointPrevPrev);
                    previousPrevious = pointPrevious.GetPreviousNode();
                }
            }

            // Invalidate next(s)
            if (pointNext != null)
            {
                AvlNode <MutablePoint> nextNext = pointNext.GetNextNode();
                for (; ;)
                {
                    if (nextNext == null)
                    {
                        break;
                    }

                    invalidPoint = !this.IsPointToTheRightOfOthers(pointNew.Item, nextNext.Item, pointNext.Item);
                    if (!invalidPoint)
                    {
                        break;
                    }

                    MutablePoint pointNextNext = nextNext.Item;
                    this.RemoveNode(pointNext);
                    pointNext = this.GetNode(pointNextNext);
                    nextNext  = pointNext.GetNextNode();
                }
            }
        }