感谢 Gene 的评论,我看到我建议的早期算法并不总是有效,因为它假设级别 x 的最大节点小于级别 x-1 的最小节点,这不是一个合理的假设。
然而,我相信这个可以有效地完成这项工作:
public static int[] kMin(FibonacciHeap H, int k) {
if (H == null || H.isEmpty() || k <= 0)
return new int[0];
HeapNode tree = H.findMin();
int rank = tree.getRank();
int size = H.size();
size = (int) Math.min(size, Math.pow(2, rank));
if (k > size)
k = size;
int[] result = new int[k];
FibonacciHeap heap = new FibonacciHeap();
HeapNode next = H.findMin();
for(int i = 0; i < k; i++) { // k iterations
if(next != null)
for (Iterator<HeapNode> iter = next.iterator(); iter.hasNext(); ) { // rank nCr next.getParent().getRank() iterations.
next = iter.next();
HeapNode node = heap.insert(next.getKey()); // O(1)
node.setFreePointer(next);
}
next = heap.findMin().getFreePointer();
result[i] = next.getKey();
heap.deleteMin(); // O(log n) amortized cost.
next = next.child;
}
return result;
}
“freePointer”是 HeapNode 中的一个字段,我可以在其中存储指向另一个 HeapNode 的指针。它基本上是大多数堆拥有的“信息字段”。
设 r 为树的秩。每次迭代我们最多向外部堆插入 r 个项目。此外,每次迭代我们都使用 Delete-Min 从堆中删除一项。因此,插入的总成本为O(kr)
,而 的总成本Delete-Min
为O(k*log(k)+k*log(r))
。所以一切的总成本变成O(k(log(k)+r))