让我们合并两个二项堆,一个为 n 级,另一个为 m 级,其中 m 不大于 n。每个二项式堆都可以表示为一个二进制数。例如:1010 是具有 3 度二叉树和 1 度二叉树的二叉堆。以下是合并函数的一些 Python 代码:
def merge(heap_one, heap_two):
# heap_one has n nodes and heap_two has m nodes
# A BinomialHeap object consists of an array of BinomialTrees called trees
# where each element of the array is a BinomialTree or is None
for tree in heap_two.trees:
if tree != None:
heap_one.add_tree(tree)
假设 heap_one 是 1111,heap_two 是 111。这两个堆分别是它们等级的最坏情况堆。我的意思是,1111 比 1011 或 1101 或 1000 差。heap_one 中的节点数为 1+2+4+8 = 15。heap_one 的等级为 4 = log(15 + 1)。heap_two 中的节点数为 1+2+4 = 7。 heap_two 的秩为 3 = log(7 + 1)。我们在这里使用以 2 为底的日志。
对于合并,按照代码,我们首先执行 1111 + 1,然后是 (1111 + 1) + 10,然后是 ((1111 + 1) + 10) + 100。1111 + 1 = 10000 - 生成了 4 个进位。10000 + 10 = 10010 -- 产生 0 个进位。10010 + 100 = 10110 -- 产生 0 个进位。总数 在这个例子中,产生的进位数是 4。你不能有一个没有的例子。产生的进位大于 log n。
为了合并 1001 和 101,产生 1 个进位。为了合并 1111 和 1111,产生了 4 个进位。为了合并 11111 和 1111,产生了 5 个进位。
让我们回到合并 1111 和 111。四个进位是在循环的第一次迭代中生成的,使 heap_one 为 10000。这是一个 O(logn) 操作。当产生 0 个进位时,它是一个 O(1) 操作。通俗地说,logn + (logm - 1) * 1 = logn + logm - 1 < 2logn - 1 < 2logn O(logn) + (O(logm) - 1) = O(logn + logm) = O(logn) 因为 m <= n。注意:logm - 1 是编号。heap_two 中不产生进位的节点。
让我们合并 1011 和 111。1011 不是最坏情况的 4 级二项堆。1011 + 1 = 1100 -- 产生 2 个进位。1100 + 10 = 1110 -- 产生 0 个进位。1110 + 100 = 10110 -- 生成 2 个进位。前 2 个进位是从 1011 的第 0 位和第 1 位生成的。接下来的 2 个进位是从第 2 位和第 3 位生成的。因此,合并是一个 O(logn) 操作。