/// <summary> Remove the smallest item from the priority queue.</summary>
        /// <returns> the smallest item, or null, if empty.
        /// </returns>
        public virtual Comparable deleteMin()
        {
            if (Empty)
            {
                return(null);
            }

            int        minIndex = findMinIndex();
            Comparable minItem  = theTrees[minIndex].element;

            BinomialNode deletedTree = theTrees[minIndex].leftChild;

            BinomialQueue deletedQueue = new BinomialQueue();

            deletedQueue.currentSize = (1 << minIndex) - 1;
            for (int j = minIndex - 1; j >= 0; j--)
            {
                deletedQueue.theTrees[j] = deletedTree;
                deletedTree = deletedTree.nextSibling;
                deletedQueue.theTrees[j].nextSibling = null;
            }

            theTrees[minIndex] = null;
            currentSize       -= (deletedQueue.currentSize + 1);

            try
            {
                merge(deletedQueue);
            }
            catch (Overflow e)
            {
            }
            return(minItem);
        }
        /// <summary> Insert into the priority queue, maintaining heap order.
        /// This implementation is not optimized for O(1) performance.
        /// </summary>
        /// <param name="x">the item to insert.
        /// </param>
        /// <exception cref="Overflow">if capacity exceeded.
        /// </exception>
        public virtual void  insert(Comparable x)
        {
            BinomialQueue oneItem = new BinomialQueue();

            oneItem.currentSize = 1;
            oneItem.theTrees[0] = new BinomialNode(x);

            merge(oneItem);
        }
        public static void  Main(System.String[] args)
        {
            int           numItems = 10000;
            BinomialQueue h        = new BinomialQueue();
            BinomialQueue h1       = new BinomialQueue();
            int           i        = 37;

            System.Console.Out.WriteLine("Starting check.");
            try
            {
                for (i = 37; i != 0; i = (i + 37) % numItems)
                {
                    if (i % 2 == 0)
                    {
                        h1.insert(new MyInteger(i));
                    }
                    else
                    {
                        h.insert(new MyInteger(i));
                    }
                }

                h.merge(h1);
                for (i = 1; i < numItems; i++)
                {
                    if (((MyInteger)(h.deleteMin())).intValue() != i)
                    {
                        System.Console.Out.WriteLine("Oops! " + i);
                    }
                }
            }
            catch (Overflow e)
            {
                System.Console.Out.WriteLine("Unexpected overflow");
            }
            System.Console.Out.WriteLine("Check done.");
        }
        /// <summary> Merge rhs into the priority queue.
        /// rhs becomes empty. rhs must be different from this.
        /// </summary>
        /// <param name="rhs">the other binomial queue.
        /// </param>
        /// <exception cref="Overflow">if result exceeds capacity.
        /// </exception>
        public virtual void  merge(BinomialQueue rhs)
        {
            if (this == rhs)
            {
                // Avoid aliasing problems
                return;
            }

            if (currentSize + rhs.currentSize > capacity())
            {
                throw new Overflow();
            }

            currentSize += rhs.currentSize;

            BinomialNode carry = null;

            for (int i = 0, j = 1; j <= currentSize; i++, j *= 2)
            {
                BinomialNode t1 = theTrees[i];
                BinomialNode t2 = rhs.theTrees[i];

                int whichCase = t1 == null?0:1;
                whichCase += (t2 == null?0:2);
                whichCase += (carry == null?0:4);

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

                case 2:                          /* Only rhs */
                    theTrees[i]     = t2;
                    rhs.theTrees[i] = null;
                    break;

                case 4:                          /* Only carry */
                    theTrees[i] = carry;
                    carry       = null;
                    break;

                case 3:                          /* this and rhs */
                    carry       = combineTrees(t1, t2);
                    theTrees[i] = rhs.theTrees[i] = null;
                    break;

                case 5:                          /* this and carry */
                    carry       = combineTrees(t1, carry);
                    theTrees[i] = null;
                    break;

                case 6:                          /* rhs and carry */
                    carry           = combineTrees(t2, carry);
                    rhs.theTrees[i] = null;
                    break;

                case 7:                          /* All three */
                    theTrees[i]     = carry;
                    carry           = combineTrees(t1, t2);
                    rhs.theTrees[i] = null;
                    break;
                }
            }

            for (int k = 0; k < rhs.theTrees.Length; k++)
            {
                rhs.theTrees[k] = null;
            }
            rhs.currentSize = 0;
        }