在以下有关最小-最大堆删除-最小过程的代码段的for循环中,为什么last=(*n)/2
?这是因为在最坏的情况下,必须将x插入...的孙代的孙代,例如:树高5:最小最大最小最大最小,floor(5/2)= 2,因为在更坏的情况下,仅在第一级之后两分钟。现在再来一个:高度4:最小最大最小最大,地板(4/2)= 2,这次不起作用。我认为也许last=(*n)
会起作用,甚至for(i=1;;)
也会起作用,因为它只是检查不会发生的事情?标题的原因是IIRC最小-最大堆删除的时间复杂度是
O(log n)
,但(*n)/2
使它看起来像O(n)
。
element delete_min(element heap[], int *n) {
int i, last, k, parent;
element temp, x;
if (!(*n)) {
// checking
}
heap[0] = heap[1];
x = heap[(*n)--];
for (i=1, last=(*n)/2; i<=last; ) {
k = min_child_grandchild(i, *n);
if (x.key <= heap[k].key)
break;
heap[i] = heap[k];
if (k <= 2*i+1) {
i = k;
break;
}
parent = k/2;
if (x.key > heap[parent].key)
SWAP(heap[parent], x, temp);
i = k;
} // end for
heap[i] = x;
return heap[0];
}
来源:
答案 0 :(得分:1)
如果在大小n
的范围内线性迭代,则循环执行O(n)次。在这里线性表示您有一些循环索引,每次循环时都可以通过添加一个常数(通常但不一定是1:
for(i = 0; i < n; i += c) { /* Loop executes O(n) times */ }
但这不是这里发生的事情。 i
没有增加一个常数。它被设置为k
,其中k
是i
的某些子代或孙代的索引。索引最小的i
的子项位于索引2i
处;索引最小的孙子在索引4i
处。 (这些公式用于基于1的索引,这在算法描述中很常见。)
因此循环更像这样(常数c
通常为4,但绝不小于2):
for(i = 0; i < n; i *= c) { /* Loop executes O(log n) times */ }