如果删除的平均情况是lg(n),这是有道理的,因为你必须使用percDown值来维护堆的完整性,为什么插入和percUping堆不一样?是不是相对于输入(n)进行的比较量除以2?
答案 0 :(得分:0)
这是一个有趣的主张。我试过做一个基本的计算。如果计算错误,请查看并提及。它基本上是一个带有一些假设的机械计算。
假设:
k
元素的完整二叉树中已有2^k-1
个级别。2^k
个元素以使树具有k+1
级别。 [1..k]
(3)表示旧树中的每个元素基本上都被新元素替换。因此,向上渗透的数量将是:
k + 2 * (k-1) + 4 * (k - 2) + ... + 2^(k-1) * 1
= k + 2 * k + 4 * k + ... + 2^(k-1) * k - (2 + 2 * 2^2 + 3 * 2^3 + ... + (k - 1) * 2^(k-1))
= k * (2 + 4 + ... + 2^(k-1)) - (k * 2^k - 2 * (2^k - 1)) ......(a)
= k * (2^k - 1) - k * 2^k + 2 ^(k+1) - 2
= k * 2^k - k - k * 2^k + 2^(k+1) - 2
= 2^(k+1) - (k + 2)
(a)计算here。
因此,我们有使用2^k
步骤渗透的(2^(k+1) - (k+1) - 1)
个元素。因此,每个元素的平均费用为O((2^(k+1) - (k+1) - 1) / 2^k) = O(2 - (k+2)/2^k)
,即O(1)
。
因此我们可以假设插入成本不变。
注意:如果我们假设某个元素会被概率0.5
替换,我们可以将其纳入上面的计算中,并且我认为它会导致该部门接近1
。
答案 1 :(得分:0)
为什么插入和percUping堆不一样?
当你删除head(h)时,你将它与堆中的最后一个元素交换,这是最长子树中的最低元素(l)。将l放入更高级别的堆的概率被认为是低到可以忽略的,因为它已经是其子树的最低元素。
存在特殊情况。例如,包含N个相等整数的堆将在O(1)中进行头抽取。但这不是一般情况。
答案 2 :(得分:0)
当我开始学习二进制堆时,我只是想知道完全相同的事情。我在C中编写了一个实现,当我计算不同的操作时,我对此现象感到困惑。在给出一些思考之后,我的直觉是,就像其他人提到的那样,当删除元素时,它在堆中的位置被最后一个元素替换,即属于底部的元素,因此将保证必须下沉到底部。在我的测试中,我只尝试删除堆的顶部元素,因此这些删除总是导致遍历堆的整个高度(log n)。
插入另一方面,将新元素放在底部,让它浮起来。我认为,由于堆的大多数元素都集中在较低级别,因此新节点很可能只有一次或两次跳转就能达到正确的位置。即使节点的值是整个堆的平均值,它通常也不需要一直跳到堆的垂直中间层(看作包含堆的底层) 2 ^ x个元素,实际上包含整个堆的一半以上的节点)。不知道这是否有意义,但它对我有用:)。
现在,如果删除我们正在谈论删除任何给定的元素而不仅仅是最重要的元素我不明白为什么平均情况也不应该是O(1),因为那时我们应该是最多的可能会删除底部附近的东西...