/// <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; }
/// <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; } }