예제 #1
0
        /// <summary>
        /// Removes the tree root of a binomial tree given the tree root and the <see cref="BinomialNode"/> before it.
        /// </summary>
        /// <param name="treeRoot">The root node of the binomial tree.</param>
        /// <param name="previous">The <see cref="BinomialNode"/> before the tree root.</param>
        internal void RemoveBinomialTreeRoot(BinomialNode treeRoot, BinomialNode previous)
        {
            if (treeRoot == head)
            {
                head = head.Sibling;
            }
            else
            {
                if (previous != null)
                {
                    previous.Sibling = treeRoot.Sibling;
                }
            }

            // Reversing order of root children and creating a new heap
            BinomialNode newHead = null;
            var          child   = treeRoot.Child;

            while (child != null)
            {
                var next = child.Sibling;
                child.Sibling = newHead;
                child.Parent  = null;
                newHead       = child;
                child         = next;
            }

            var newHeap = new BinomialMinHeap <T>(newHead);

            Merge(newHeap);
        }
예제 #2
0
        /// <summary>
        /// Adds an element to the <see cref="BinomialMinHeap{T}"/>.
        /// </summary>
        /// <param name="value">The value to add.</param>
        public void Add(T value)
        {
            var newNode  = new BinomialNode(value);
            var tempHeap = new BinomialMinHeap <T>(newNode);

            Merge(tempHeap);
        }
예제 #3
0
        /// <summary>
        /// Returns a new <see cref="BinomialMinHeap{T}"/> containing the elements of the <see cref="BinomialMaxHeap{T}"/>.
        /// </summary>
        /// <returns>Returns a new <see cref="BinomialMinHeap{T}"/> containing the elements of the <see cref="BinomialMaxHeap{T}"/>.</returns>
        public BinomialMinHeap <T> ToMinHeap()
        {
            var minHeap = new BinomialMinHeap <T>();

            minHeap.Heapify(ToArray());
            return(minHeap);
        }
예제 #4
0
        /// <summary>
        /// Merges the elements of the <see cref="BinomialMinHeap{T}"/> with the other given <see cref="BinomialMinHeap{T}"/>. The other <see cref="BinomialMinHeap{T}"/> is cleared after the merging.
        /// </summary>
        /// <param name="otherMinHeap">The other <see cref="BinomialMinHeap{T}"/> used for merging.</param>
        public void Merge(BinomialMinHeap <T> otherMinHeap)
        {
            // if the given heap has no elements
            if (otherMinHeap.head == null)
            {
                return;
            }

            // if this heap is empty
            if (head == null)
            {
                // copy the head of the other heap and clear it
                head  = otherMinHeap.head;
                Count = otherMinHeap.Count;
                otherMinHeap.Clear();
                return;
            }

            // if both heaps have elements

            BinomialNode newHead;

            var firstHeapNextNode  = head;
            var secondHeapNextNode = otherMinHeap.head;

            // Set the heap head of lower order as the new head
            if (head.Degree <= otherMinHeap.head.Degree)
            {
                newHead           = head;
                firstHeapNextNode = firstHeapNextNode.Sibling;
            }
            else
            {
                newHead            = otherMinHeap.head;
                secondHeapNextNode = secondHeapNextNode.Sibling;
            }

            var curNode = newHead;

            // Iterating over the roots of the binomial trees of the heaps and
            // sorting them by order(binomial tree order)
            while (firstHeapNextNode != null && secondHeapNextNode != null)
            {
                if (firstHeapNextNode.Degree <= secondHeapNextNode.Degree)
                {
                    curNode.Sibling   = firstHeapNextNode;
                    firstHeapNextNode = firstHeapNextNode.Sibling;
                }
                else
                {
                    curNode.Sibling    = secondHeapNextNode;
                    secondHeapNextNode = secondHeapNextNode.Sibling;
                }

                curNode = curNode.Sibling;
            }

            if (firstHeapNextNode != null)
            {
                curNode.Sibling = firstHeapNextNode;
            }
            else
            {
                curNode.Sibling = secondHeapNextNode;
            }

            head = newHead;

            // After the new head links to the binomial tree roots sorted by order
            // we have to leave at most one tree of each order. We can do this by merging every
            // two trees of order k to a new tree of order k + 1

            BinomialNode previous = null;
            BinomialNode current  = newHead;
            BinomialNode next     = newHead.Sibling;

            while (next != null)
            {
                // if the order of the trees is different
                // or we have 3 trees of the same order we continue onwards.
                // Having 3 trees of order k. We can leave one with order k and merge
                // the next 2 to create a tree of order k + 1
                // Note: It is not possible to have more than 3 trees of order k,
                // because a heap has at most one tree of each order. So merging two heaps
                // we get maximum of two trees with the same order and having 2 trees
                // of order k and 2 trees of order k + 1. We merge the 2 trees of order k
                // to a tree of order k + 1 and now we have 3 trees of order k + 1(leaving one
                // and merging the other 2). So having 4 trees of same order is not possible
                if (current.Degree != next.Degree ||
                    ((next.Sibling?.Degree ?? -1) == current.Degree))
                {
                    previous = current;
                    current  = next;
                }
                else// if we need to merge 2 trees of same order
                {
                    // if the current node is smaller than or equal to the next
                    if (current.Value.CompareTo(next.Value) <= 0)
                    {
                        current.Sibling = next.Sibling;
                        MergeBinomialTrees(smallerNode: current, biggerNode: next);
                    }
                    else// if the current is bigger that the next
                    {
                        // we set the previous node link to this one
                        if (previous == null)
                        {
                            newHead = next;
                        }
                        else
                        {
                            previous.Sibling = next;
                        }

                        MergeBinomialTrees(smallerNode: next, biggerNode: current);
                        current = next;
                    }
                }
                // Here current has became the next node,
                // so the new next node is the sibling of the current
                next = current.Sibling;
            }

            // At last we update the head and the count
            head   = newHead;
            Count += otherMinHeap.Count;
            // We clear the other heap
            otherMinHeap.Clear();
        }