/// <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); }
/// <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); }
/// <summary> /// Returns a new <see cref="BinomialMinHeap{T}"/> containing the elements of the <see cref="BinomialMaxHeap{T}"/>. /// </summary> /// <returns>Returns a new <see cref="BinomialMinHeap{T}"/> containing the elements of the <see cref="BinomialMaxHeap{T}"/>.</returns> public BinomialMinHeap <T> ToMinHeap() { var minHeap = new BinomialMinHeap <T>(); minHeap.Heapify(ToArray()); return(minHeap); }
/// <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(); }