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

            var minTree = heapForest.Head;
            var current = heapForest.Head;

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

                if (minTree.Data.Value.CompareTo(current.Data.Value) > 0)
                {
                    minTree = current;
                }
            }

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

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

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

            mergeSortedForests(newHeapForest);

            meld();

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

            Count--;

            return(minTree.Data.Value);
        }
        /// <summary>
        /// Time complexity: O(1).
        /// </summary>
        internal void Union(DoublyLinkedList <T> newList)
        {
            if (Head == null)
            {
                Head = newList.Head;
                Tail = newList.Tail;
                return;
            }

            if (newList.Head == null)
            {
                return;
            }

            Head.Previous     = newList.Tail;
            newList.Tail.Next = Head;

            Head = newList.Head;
        }
예제 #3
0
        /// <summary>
        /// Shrink if needed
        /// </summary>
        private void shrink()
        {
            if (Math.Abs(filledBuckets - bucketSize * 0.3) < tolerance && bucketSize / 2 > initialBucketSize)
            {
                filledBuckets = 0;
                //reduce array by half
                var newBucketSize = bucketSize / 2;

                var smallerArray = new DoublyLinkedList <HashSetNode <TV> > [newBucketSize];

                for (int i = 0; i < bucketSize; i++)
                {
                    var item = hashArray[i];

                    //hashcode changes when bucket size changes
                    if (item?.Head != null)
                    {
                        var current = item.Head;

                        //find new location for each item
                        while (current != null)
                        {
                            var next = current.Next;

                            var newIndex = Math.Abs(current.Data.Value.GetHashCode()) % newBucketSize;

                            if (smallerArray[newIndex] == null)
                            {
                                filledBuckets++;
                                smallerArray[newIndex] = new DoublyLinkedList <HashSetNode <TV> >();
                            }

                            smallerArray[newIndex].InsertFirst(current);

                            current = next;
                        }
                    }
                }

                hashArray = smallerArray;
            }
        }
        /// <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);
        }
        /// <summary>
        /// Merges the given sorted forest to current sorted Forest
        /// and returns the last inserted node (pointer required for update-key)
        /// </summary>
        private void mergeSortedForests(DoublyLinkedList <BinomialHeapNode <T> > newHeapForest)
        {
            var @new = newHeapForest.Head;

            if (heapForest.Head == null)
            {
                heapForest = newHeapForest;
                return;
            }

            var current = heapForest.Head;

            //insert at right spot and move forward
            while (@new != null && current != null)
            {
                if (current.Data.Degree < @new.Data.Degree)
                {
                    current = current.Next;
                }
                else if (current.Data.Degree > @new.Data.Degree)
                {
                    heapForest.InsertBefore(current, new DoublyLinkedListNode <BinomialHeapNode <T> >(@new.Data));
                    @new = @new.Next;
                }
                else
                {
                    //equal
                    heapForest.InsertAfter(current, new DoublyLinkedListNode <BinomialHeapNode <T> >(@new.Data));
                    current = current.Next;
                    @new    = @new.Next;
                }
            }

            //copy left overs
            while (@new != null)
            {
                heapForest.InsertAfter(heapForest.Tail, new DoublyLinkedListNode <BinomialHeapNode <T> >(@new.Data));
                @new = @new.Next;
            }
        }