有人能解释一下构建堆的复杂性吗?
将项插入到堆中是O(logn),并且插入被重复n/2次(剩余的是叶子,不能违反堆属性)。所以,我认为这意味着复杂性应该是O(n log n)。
换言之,对于我们“heapify”的每个项目,它有可能必须为堆的每个级别(即logn级别)过滤(即筛选)一次。
我错过了什么?
有人能解释一下构建堆的复杂性吗?
将项插入到堆中是O(logn),并且插入被重复n/2次(剩余的是叶子,不能违反堆属性)。所以,我认为这意味着复杂性应该是O(n log n)。
换言之,对于我们“heapify”的每个项目,它有可能必须为堆的每个级别(即logn级别)过滤(即筛选)一次。
我错过了什么?
当前回答
我们通过计算每个节点可以进行的最大移动量来获得堆构建的运行时。所以我们需要知道每行中有多少个节点,每个节点离它们的距离有多远。
从根节点开始,下一行的节点数是前一行的两倍,因此,通过回答节点数可以增加一倍,直到没有剩余节点,我们可以得到树的高度。或者用数学术语来说,树的高度是log2(n),n是数组的长度。
为了计算一行中的节点,我们从后面开始,我们知道n/2个节点位于底部,所以除以2,我们得到前一行,依此类推。
基于此,我们得到了筛选方法的公式:(0*n/2)+(1*n/4)+(2*n/8)+…+(log2(n)*1)
最后一个段落中的术语是树的高度乘以根处的一个节点,第一个段落中术语是底部行中的所有节点乘以它们可以移动的长度,0。smart中的相同公式:
把n带回来,我们得到了2*n,2可以被丢弃,因为它是一个常数,而tada是Siftdown方法最坏的运行时:n。
其他回答
直观地:
“复杂性应该是O(nLog n)……对于我们“heapify”的每个项目,它有可能必须为堆的每个级别(即log n级别)过滤一次。”
不完全是。您的逻辑不会产生严格的界限——它会过度估计每个堆的复杂性。如果从下往上构建,插入(heapify)可以比O(log(n))小得多。流程如下:
(步骤1)前n/2个元素位于堆的底行。h=0,因此不需要heapify。
(步骤2)接下来的n/22个元素从底部向上排列在第1行。h=1,将过滤器向下堆1级。
(步骤i)接下来的n/2i元素从底部排i。h=i,将过滤器堆成i级。
(步骤log(n))最后一个n/2log2(n)=1元素从底部向上进入行log(n。h=log(n),heapify向下过滤log(n)级别。
注意:在第一步之后,1/2的元素(n/2)已经在堆中,我们甚至不需要调用heapify一次。此外,请注意,实际上只有一个元素,即根元素,会导致完整的log(n)复杂性。
理论上:
构建大小为N的堆的总步骤N可以用数学公式表示。
在高度i处,我们已经显示(上面)将有n/2i+1个元素需要调用heapify,并且我们知道高度i处的heapify是O(i)。这给出了:
最后求和的解可以通过取众所周知的几何级数方程两边的导数来找到:
最后,将x=1/2代入上式得到2。将其代入第一个方程得出:
因此,步骤总数大小为O(n)
在构建堆时,假设您采用的是自下而上的方法。
您获取每个元素并将其与子元素进行比较,以检查该元素对是否符合堆规则。因此,叶被免费包含在堆中。那是因为他们没有孩子。向上移动,叶子正上方节点的最坏情况是1次比较(最多只能与一代孩子进行比较)再往上看,他们的直系父母最多可以与两代子女相比。继续朝着相同的方向,在最坏的情况下,您将对根进行log(n)比较。并且log(n)-1用于其直系子代,log(n)-2用于其直系子女,依此类推。所以总结起来,你会得到类似log(n)+{log(n(n)-1}*2+{log(n)-2}*4+…..+1*2^{(logn)-1},它只是O(n)。
假设堆中有N个元素。则其高度为Log(N)
现在您要插入另一个元素,那么复杂性将是:Log(N),我们必须一直向上比较到根。
现在您有N+1个元素&高度=对数(N+1)
利用归纳法可以证明插入的复杂性为∑logi。
现在使用
log a+log b=log ab
这简化为:∑logi=log(n!)
实际上是O(NlogN)
But
我们在这里做了一些错事,因为在所有情况下,我们都没有达到顶峰。因此,在执行大多数时候,我们可能会发现,我们甚至不会爬到树的一半。因此,可以通过使用上面答案中给出的数学来优化这个界限,使其具有另一个更紧密的界限。
在堆上进行了详细的实验之后,我意识到了这一点。
基本上,在构建堆时,只在非叶节点上完成工作。。。所做的工作是减少交换量以满足堆条件。。。换句话说(在最坏的情况下),数量与节点的高度成比例。。。总之,问题的复杂性与所有非叶节点的高度之和成正比。。即(2^h+1-1)-h-1=n--1=O(n)
我们知道堆的高度是log(n),其中n是元素的总数当我们执行heapify操作时,最后一级(h)的元素甚至不会移动一步。第二个最后一级(h-1)的元素数为2h-1,它们最多可以移动1级(在堆化期间)。类似地,对于第i层,我们有2i个元素可以移动h-i个位置。
因此,移动总数:
S=2h*0+2h-1*1+2h-2*2+。。。20*小时
S=2h{1/2+2/22+3/23+…h/2h}-------------------------------------------------1
这是AGP系列,用于解决两边除以2的问题S/2=2h{1/22+2/23+…h/2h+1}-------------------------------------------------2
从1中减去方程式2得到S/2=2h{1/2+1/22+1/23+…+1/2h+h/2h+1}S=2h+1{1/2+1/22+1/23+…+1/2h+h/2h+1}
现在1/2+1/22+1/23++1/2h是减小GP,其和小于1(当h趋于无穷大时,和趋于1)。在进一步的分析中,让我们对和取一个上限,即1。
这给出了:S=2h+1{1+h/2h+1}=2h+1+h~2h+h
h=对数(n),2h=n因此S=n+log(n)T(C)=O(n)