예제 #1
0
        /// <summary>
        ///   Deletes the specified item from this heap.
        /// </summary>
        /// <param name="item">Item to be deleted.</param>
        /// <exception cref="InvalidOperationException">
        ///   This heap is empty.
        /// </exception>
        public void Delete(IPriorityQueueItem <T> item)
        {
            if (this.IsEmpty())
            {
                throw new InvalidOperationException("This heap is empty.");
            }

            if (item is FibonacciHeapItem <T> )
            {
                FibonacciHeapItem <T> fibHeapItem = (FibonacciHeapItem <T>)item;

                // Cut the edge joining the containing node x to its parent p.
                FibonacciHeapNode <T> x = fibHeapItem.ContainingNode;

                if (x.Parent == null)
                {
                    // x is originally a root - just remove it from the list of roots.
                    if (x == this.minimumNode)
                    {
                        this.DeleteMin();
                        return;
                    }
                    else
                    {
                        x.LeftSibling.RightSibling = x.RightSibling;
                        x.RightSibling.LeftSibling = x.LeftSibling;
                    }
                }
                else
                {
                    /*
                     * As x is not a root, remove it from the list of children of
                     * its parent and decrease its parent's rank.
                     */
                    x.CutEdgeToParent(false, this);

                    /*
                     * Form a new list of roots by concatenating the list of children of
                     * x with the original list of roots.
                     */
                    if (x.SomeChild != null)
                    {
                        this.minimumNode.RightSibling.LeftSibling = x.SomeChild.LeftSibling;
                        x.SomeChild.LeftSibling.RightSibling      = this.minimumNode.RightSibling;

                        this.minimumNode.RightSibling = x.SomeChild;
                        x.SomeChild.LeftSibling       = this.minimumNode;
                    }
                }

                this.count--;
            }
            else
            {
                throw new ArgumentException("Can work only on Fibonacci Heap items.", "item");
            }
        }
예제 #2
0
        /// <summary>
        ///   Inserts the passed item with the specified key into this heap.
        /// </summary>
        /// <param name="item">Item to insert.</param>
        /// <param name="key">Key of the item to insert.</param>
        /// <returns>Container that holds the passed item.</returns>
        public IPriorityQueueItem <T> Insert(T item, double key)
        {
            // Contruct a new container for the passed item.
            FibonacciHeapItem <T> newItem = new FibonacciHeapItem <T>(item, key);

            // Create a new heap consisting of one node containing the passed item.
            FibonacciHeap <T> newHeap = new FibonacciHeap <T>();

            newHeap.minimumNode = new FibonacciHeapNode <T>(newItem);
            newHeap.count       = 1;

            // Meld this heap and the new one.
            this.Meld(newHeap);

            return(newItem);
        }
예제 #3
0
        /// <summary>
        ///   Decreases the key of the specified item in this heap by subtracting
        ///   the passed non-negative real number <c>delta</c>.
        /// </summary>
        /// <param name="item">Item to decrease the key of.</param>
        /// <param name="delta">Non-negative real number to be subtracted from the item's key.</param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///   <c>delta</c> is negative.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        ///   This heap is empty.
        /// </exception>
        public void DecreaseKey(IPriorityQueueItem <T> item, double delta)
        {
            if (delta < 0)
            {
                throw new ArgumentOutOfRangeException("delta", "delta has to be non-negative.");
            }

            if (this.IsEmpty())
            {
                throw new InvalidOperationException("This heap is empty.");
            }

            if (item is FibonacciHeapItem <T> )
            {
                FibonacciHeapItem <T> fibHeapItem = (FibonacciHeapItem <T>)item;

                // Subtract delta from the key of the passed item.
                fibHeapItem.Key -= delta;

                // Cut the edge joining the containing node x to its parent p.
                FibonacciHeapNode <T> x = fibHeapItem.ContainingNode;

                if (x.Parent != null)
                {
                    /*
                     * If x is not a root, remove it from the list of children of
                     * its parent, decrease its parent's rank, and add it to the list
                     * of roots of this heap in order to preserve the heap order.
                     */
                    x.CutEdgeToParent(true, this);
                }

                // Redefine the minimum node of this heap, if necessary.
                if (fibHeapItem.Key < this.minimumNode.Item.Key)
                {
                    this.minimumNode = x;
                }
            }
            else
            {
                throw new ArgumentException("Can only work on Fibonacci Heap items.", "item");
            }
        }
예제 #4
0
        /// <summary>
        ///   Deletes the item with the minimum key in this heap and returns it.
        /// </summary>
        /// <returns>Item with the minimum key in this heap.</returns>
        /// <exception cref="InvalidOperationException">
        ///   This heap is empty.
        /// </exception>
        public IPriorityQueueItem <T> DeleteMin()
        {
            if (this.IsEmpty())
            {
                throw new InvalidOperationException("This heap is empty.");
            }

            /*
             * Remove the minimum node x from this heap and concatenate the list of
             * children of x with the list of roots of this heap other than x.
             */
            FibonacciHeapNode <T> x           = this.minimumNode;
            FibonacciHeapItem <T> minimumItem = x.Item;

            this.count--;

            // Remember some node to start with the linking step later on.
            FibonacciHeapNode <T> someListNode;

            if (x.RightSibling == x)
            {
                if (x.SomeChild == null)
                {
                    // The heap consists of only the root node.
                    this.minimumNode = null;

                    return(minimumItem);
                }
                else
                {
                    // Root has no siblings - apply linking step to list of children.
                    someListNode = x.SomeChild;
                }
            }
            else
            {
                if (x.SomeChild == null)
                {
                    // Root has no children - apply linking step to list of siblings.
                    x.LeftSibling.RightSibling = x.RightSibling;
                    x.RightSibling.LeftSibling = x.LeftSibling;

                    someListNode = x.LeftSibling;
                }
                else
                {
                    // Concatenate children and siblings and apply linking step.
                    x.LeftSibling.RightSibling           = x.SomeChild;
                    x.SomeChild.LeftSibling.RightSibling = x.RightSibling;
                    x.RightSibling.LeftSibling           = x.SomeChild.LeftSibling;
                    x.SomeChild.LeftSibling = x.LeftSibling;

                    someListNode = x.SomeChild;
                }
            }

            // Linking Step.

            /*
             * Create an hashtable indexed by rank, from one up to the maximum
             * possible rank, each entry pointing to a tree root.
             */
            Dictionary <int, FibonacciHeapNode <T> > rankIndexedRoots = new Dictionary <int, FibonacciHeapNode <T> >();

            // Insert the roots one-by-one into the appropriate table positions.
            FibonacciHeapNode <T> nextOldRoot = someListNode;

            do
            {
                FibonacciHeapNode <T> shouldBeInserted = nextOldRoot;
                nextOldRoot = nextOldRoot.RightSibling;

                while (shouldBeInserted != null)
                {
                    /*
                     * If the position is already occupied, perform a linking
                     * step and attempt to insert the root of the new tree into
                     * the next higher position.
                     */
                    if (rankIndexedRoots.ContainsKey(shouldBeInserted.Rank))
                    {
                        FibonacciHeapNode <T> other = rankIndexedRoots[shouldBeInserted.Rank];
                        rankIndexedRoots.Remove(shouldBeInserted.Rank);
                        shouldBeInserted = shouldBeInserted.Link(other);
                    }
                    else
                    {
                        rankIndexedRoots.Add(shouldBeInserted.Rank, shouldBeInserted);
                        shouldBeInserted = null;
                    }
                }
            }while (nextOldRoot != someListNode);

            /*
             * Form a list of the remaining roots, in the process finding a root
             * containing an item of minimum key to serve as the minimum node of the
             * modified heap.
             */
            List <FibonacciHeapNode <T> > newRoots = rankIndexedRoots.Values.ToList();

            // Start with the first new root.
            FibonacciHeapNode <T> firstNewRoot = newRoots[0];

            this.minimumNode        = firstNewRoot;
            this.minimumNode.Parent = null;

            FibonacciHeapNode <T> currentNewRoot = firstNewRoot;

            for (int i = 1; i < newRoots.Count; i++)
            {
                // Get the next new root.
                FibonacciHeapNode <T> previousNewRoot = currentNewRoot;
                currentNewRoot = newRoots[i];

                // Update pointers.
                previousNewRoot.RightSibling = currentNewRoot;
                currentNewRoot.LeftSibling   = previousNewRoot;
                currentNewRoot.Parent        = null;

                // Check for new minimum node.
                if (currentNewRoot.Item.Key < this.minimumNode.Item.Key)
                {
                    this.minimumNode = currentNewRoot;
                }
            }

            currentNewRoot.RightSibling = firstNewRoot;
            firstNewRoot.LeftSibling    = currentNewRoot;

            return(minimumItem);
        }