对于那些非常了解这一点的人,请阅读下面的粗体文字以了解实际问题。
我知道合并两个相同等级的二叉树是O(1),因为所有必要的是将T1的头部作为另一个的孩子。我也知道在二项式堆中插入一个等于或小于最小阶树的顺序的树是O(logN),因为"结转"合并的效果适用。想象一下T_0,T_1,T_2,...,T_n(其中下标是顺序)的二项式堆,我们添加一个新的T'这将导致n次结合相同顺序的树的结转。我们知道n = log(N)。
在merge函数中,两个堆以树的形式添加到新堆树中,采用mergesort方式。我们将任一堆的最低阶树添加到新堆中,如果两个命令相同,那么我们合并它(O(1))并在生成后将其插入(O(logN))生成树递归。由于我们将首先插入最低阶的树,因此合并将始终插入一个等于或小于新堆中第一棵树的树。
我很困惑为什么合并功能是O(logN),而不是O(logN * logN)。我们知道每个插入都是O(logN),我们有logN树,其中N = N1 + N2,其中N1和N2是每个起始堆中的元素数。 如果我们在结构中有两个堆,导致插入的遗留效应会发生在每个插入到新堆中的情况,那么它不是O(logN * logN)吗?
也许我在这里错过了一些关键的理解。任何帮助表示赞赏!如果你告诉我在我的理解中哪里出错了,请特别感谢:)
答案 0 :(得分:1)
您可能不了解该算法。当我们有两个相同顺序的树时,我们不要合并(O(1))它并插入(O(log N))"。你认为,当我们得到这样的"合并"树我们离开它,最后,我们逐节点地插入它,对吧?然后使它成为O(logN):当你有两个k阶的树时,你合并它们并获得一个k + 1的树。现在,根据您正在合并的堆中有多少k + 1个订单树,您有一个,两个或树k + 1个订单树:
如果1这棵树只是合并堆的一部分
如果2合并这两个并在k + 2顺序树上再次执行此操作
如果3是合并堆的一部分,并且将其他2合并到k + 2顺序树
所有这些都是O(1)所以当你以log(n)+ 1个命令执行时,你得到O(log(n))堆合并。
答案 1 :(得分:0)
让我们合并两个二项式堆,一个是等级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为底使用log。
对于合并,按代码进行,我们首先执行1111 + 1,然后执行(1111 +1)+ 10,然后执行((1111 +1)+ 10)+100。1111 +1 = 10000-这是4产生。 10000 + 10 = 10010-产生0个进位10010 + 100 = 10110-产生了0个进位。总数在此示例中,生成的进位总数为4。您不能举一个没有的例子。产生的进位总数大于对数n。
为了合并1001和101,产生1进位。为了合并1111和1111,产生了4个进位。为了合并11111和1111,生成了5个进位。
让我们回到合并1111和111。这四个进位是在循环的第一次迭代中生成的,使得heap_one10000。这是一个O(logn)操作。 当产生0进位时,这是O(1)运算。 非正式地,logn +(logm-1)* 1 = logn + logm-1 <2logn-1 <2logn 因为m <= n,所以O(logn)+(O(logm)-1)= O(logn + logm)= O(logn)。 注意:logm-1是编号。不产生进位的heap_two中的节点数。
让我们合并1011和111。1011不是最坏情况的4级二项式堆。 1011 +1 = 1100-产生2个进位。 1100 + 10 = 1110-产生了0个进位1110 + 100 = 10110-产生2个进位前两个进位是从1011的第0和第1位产生的。接下来的2个进位是从第2和第3位产生的。因此,合并是一个O(logn)操作。