Example #1
0
 public BinomialNode(T value, BinomialNode <T> parent, BinomialNode <T> sibling, BinomialNode <T> child)
 {
     Value   = value;
     Parent  = parent;
     Sibling = sibling;
     Child   = child;
 }
Example #2
0
        /// <summary>
        /// Removes and returns the min element of the <see cref="BinomialMinHeap{T}"/>.
        /// </summary>
        /// <returns>Returns the min element which was removed from the <see cref="BinomialMinHeap{T}"/>.</returns>
        public T PopMin()
        {
            if (IsEmpty)
            {
                throw new InvalidOperationException("Heap is empty!");
            }

            BinomialNode min     = head;        // min node
            BinomialNode minPrev = null;        // node before the min node
            BinomialNode current = min.Sibling; // current node in the traversal
            BinomialNode last    = min;         // the last traversed node

            while (current != null)
            {
                if (current.Value.CompareTo(min.Value) <= 0)
                {
                    min     = current;
                    minPrev = last;
                }

                last    = current;
                current = current.Sibling;
            }

            // Saving count because when removing the binomial tree root
            // the current heap is merged with a new heap with unknown
            // number of elements
            var oldCount = Count;

            RemoveBinomialTreeRoot(min, minPrev);

            Count = oldCount - 1;

            return(min.Value);
        }
Example #3
0
        /************************************************************************************************/
        /** PRIVATE HELPER FUNCTIONS                                                                    */


        /// <summary>
        /// Removes root of tree at he specified index.
        /// </summary>
        private void _removeAtIndex(int minIndex)
        {
            // Get the deletedTree
            // The min-root lies at _forest[minIndex]
            BinomialNode <T> deletedTreeRoot = _forest[minIndex].Child;

            // Exit if there was no children under old-min-root
            if (deletedTreeRoot == null)
            {
                return;
            }

            // CONSTRUCT H'' (double-prime)
            BinomialMinHeap <T> deletedForest = new BinomialMinHeap <T>();

            deletedForest._forest.Resize(minIndex + 1);
            deletedForest._size = (1 << minIndex) - 1;

            for (int i = (minIndex - 1); i >= 0; --i)
            {
                deletedForest._forest[i]         = deletedTreeRoot;
                deletedTreeRoot                  = deletedTreeRoot.Sibling;
                deletedForest._forest[i].Sibling = null;
            }

            // CONSTRUCT H' (single-prime)
            _forest[minIndex] = null;
            _size             = deletedForest._size + 1;

            Merge(deletedForest);

            // Decrease the size
            --_size;
        }
Example #4
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);
        }
Example #5
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);
        }
Example #6
0
 /// <summary>
 /// Merge two binomial trees to a new tree of higher order, given the roots of the trees.
 /// </summary>
 /// <param name="smallerNode">The <see cref="BinomialNode"/> with the smaller value.</param>
 /// <param name="biggerNode">The <see cref="BinomialNode"/> with the bigger value.</param>
 internal void MergeBinomialTrees(BinomialNode smallerNode, BinomialNode biggerNode)
 {
     biggerNode.Parent  = smallerNode;
     biggerNode.Sibling = smallerNode.Child;
     smallerNode.Child  = biggerNode;
     smallerNode.Degree++;
 }
Example #7
0
 /// <summary>
 /// Clones a tree, given it's root node.
 /// </summary>
 private BinomialNode <T> _cloneTree(BinomialNode <T> treeRoot)
 {
     if (treeRoot == null)
     {
         return(null);
     }
     return(new BinomialNode <T>()
     {
         Value = treeRoot.Value, Child = _cloneTree(treeRoot.Child), Sibling = _cloneTree(treeRoot.Sibling)
     });
 }
Example #8
0
        /// <summary>
        /// Combines two trees and returns the new tree root node.
        /// </summary>
        private BinomialNode <T> _combineTrees(BinomialNode <T> firstTreeRoot, BinomialNode <T> secondTreeRoot)
        {
            if (firstTreeRoot == null || secondTreeRoot == null)
            {
                throw new ArgumentNullException("Either one of the nodes or both are null.");
            }

            if (secondTreeRoot.Value.IsLessThan(firstTreeRoot.Value))
            {
                return(_combineTrees(secondTreeRoot, firstTreeRoot));
            }

            secondTreeRoot.Sibling = firstTreeRoot.Child;
            firstTreeRoot.Child    = secondTreeRoot;
            secondTreeRoot.Parent  = firstTreeRoot;

            return(firstTreeRoot);
        }
Example #9
0
        /// <summary>
        /// Merges the elements of another heap with this heap.
        /// </summary>
        public void Merge(BinomialMinHeap <T> otherHeap)
        {
            // Avoid aliasing problems
            if (this == otherHeap)
            {
                return;
            }

            // Avoid null or empty cases
            if (otherHeap == null || otherHeap.IsEmpty())
            {
                return;
            }

            BinomialNode <T> carryNode = null;

            _size = _size + otherHeap._size;

            // One capacity-change step
            if (_size > _forest.Count)
            {
                int newSize = Math.Max(this._forest.Count, otherHeap._forest.Count) + 1;
                this._forest.Resize(newSize);
            }

            for (int i = 0, j = 1; j <= _size; i++, j *= 2)
            {
                BinomialNode <T> treeRoot1 = (_forest.IsEmpty == true ? null : _forest[i]);
                BinomialNode <T> treeRoot2 = (i < otherHeap._forest.Count ? otherHeap._forest[i] : null);

                int whichCase = (treeRoot1 == null ? 0 : 1);
                whichCase += (treeRoot2 == null ? 0 : 2);
                whichCase += (carryNode == null ? 0 : 4);

                switch (whichCase)
                {
                /*** SINGLE CASES ***/
                case 0:         /* No trees */
                case 1:         /* Only this */
                    break;

                case 2:         /* Only otherHeap */
                    this._forest[i]      = treeRoot2;
                    otherHeap._forest[i] = null;
                    break;

                case 4:         /* Only carryNode */
                    this._forest[i] = carryNode;
                    carryNode       = null;
                    break;

                /*** BINARY CASES ***/
                case 3:         /* this and otherHeap */
                    carryNode       = _combineTrees(treeRoot1, treeRoot2);
                    this._forest[i] = otherHeap._forest[i] = null;
                    break;

                case 5:         /* this and carryNode */
                    carryNode       = _combineTrees(treeRoot1, carryNode);
                    this._forest[i] = null;
                    break;

                case 6:         /* otherHeap and carryNode */
                    carryNode            = _combineTrees(treeRoot2, carryNode);
                    otherHeap._forest[i] = null;
                    break;

                case 7:         /* all the nodes */
                    this._forest[i]      = carryNode;
                    carryNode            = _combineTrees(treeRoot1, treeRoot2);
                    otherHeap._forest[i] = null;
                    break;
                } //end-switch
            }     //end-for

            // Clear otherHeap
            otherHeap.Clear();
        }
Example #10
0
 /// <summary>
 /// Creates a new instance of the <see cref="BinomialMinHeap{T}"/> class, with the specified node as head.
 /// </summary>
 /// <param name="head">The head node.</param>
 internal BinomialMinHeap(BinomialNode head)
 {
     this.head = head;
     Count     = 1;
 }
Example #11
0
 /// <summary>
 /// Removes all elements from the <see cref="BinomialMinHeap{T}"/>.
 /// </summary>
 public void Clear()
 {
     head  = null;
     Count = 0;
 }
Example #12
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();
        }