/// <summary>
        /// Time complexity: O(log(n)).
        /// </summary>
        public T Extract()
        {
            if (heapForest.Head == null)
            {
                throw new Exception("Empty heap");
            }

            var minMaxTree = heapForest.Head;
            var current    = heapForest.Head;

            //find minMaximum tree
            while (current.Next != null)
            {
                current = current.Next;

                if (comparer.Compare(minMaxTree.Data.Value, current.Data.Value) > 0)
                {
                    minMaxTree = current;
                }
            }

            //remove tree root
            heapForest.Delete(minMaxTree);

            var newHeapForest = new DoublyLinkedList <BinomialHeapNode <T> >();

            //add removed roots children as new trees to forest
            foreach (var child in minMaxTree.Data.Children)
            {
                child.Parent = null;
                newHeapForest.InsertLast(child);
            }

            mergeSortedForests(newHeapForest);

            meld();

            removeMapping(minMaxTree.Data.Value, minMaxTree.Data);

            Count--;

            return(minMaxTree.Data.Value);
        }
        /// <summary>
        /// O(log(n)) complexity
        /// </summary>
        /// <returns></returns>
        public T ExtractMax()
        {
            if (heapForest.Head == null)
            {
                throw new Exception("Empty heap");
            }

            var maxTree = heapForest.Head;
            var current = heapForest.Head;

            //find maximum tree
            while (current.Next != null)
            {
                current = current.Next;

                if (maxTree.Data.Value.CompareTo(current.Data.Value) < 0)
                {
                    maxTree = current;
                }
            }

            //remove tree root
            heapForest.Delete(maxTree);

            var newHeapForest = new DoublyLinkedList <BinomialHeapNode <T> >();

            //add removed roots children as new trees to forest
            foreach (var node in maxTree.Data.Children)
            {
                node.Parent = null;
                newHeapForest.InsertLast(node);
            }

            MergeSortedForests(newHeapForest);

            Meld();

            Count--;

            return(maxTree.Data.Value);
        }