堆栈摊销成本分析

时间:2015-08-30 22:56:44

标签: algorithm amortized-analysis

假设我有一个由n元素数组支持的堆栈,其成本为1,推出成本为1,从数组中取出一个元素,调整数组大小的成本是移动的元素数。

1)每次堆栈变满时,我会将当前n个元素复制到一个比之前大一个元素的新数组中。我的文字声称,一系列推送将导致总费用:

1 + 2 + 3 + ... + n

这是为什么?假设我的数组以n = 1开始。

我推,堆栈现已满(成本1) 我增加了数组的大小(n = 2,成本为2) 我推和堆栈现已满(成本为1) 我增加了数组的大小(n = 3,成本为4) ...

我错过了什么?

2)假设每次堆栈满时我将数组的大小加倍。现在我从一个1元素数组开始有一系列n次推送:

我推,堆栈现已满(成本为1) 我将数组大小加倍并复制1个元素(成本为2,n = 2) 我推和堆栈现已满(成本为1) 我将数组大小加倍并复制2个元素(成本为4,n = 4) ...

这种分析看起来是否正确?

对于一系列n次推送,它将产生1 + 2 + 1 + 4 + 1 + 8 + ... + 1 + 2 ^(n / 2)

1 个答案:

答案 0 :(得分:1)

一切听起来都合理:

1)让我们从一个空堆栈开始,由一个初始大小n=1的数组表示

  • push 1. element =&gt; cost = <push-cost> = 1 =&gt;阵列现已满了
  • push 2. element =&gt; cost = <resize-cost> + <push-cost> = n + 1 = 2 =&gt; n := n + 1 = 2
  • push 3. element =&gt; cost = <resize-cost> + <push-cost> = n + 1 = 3 =&gt; n := n + 1 = 3

...依此类推,在推送1 + 2 + 3 + ... + n元素时确实会导致n的总费用。

2)您没有说出您的文字对此行为的说法,但计算方法类似:

  • push 1. element =&gt; cost = <push-cost> = 1 =&gt;阵列现已满了
  • push 2. element =&gt; cost = <resize-cost> + <push-cost> = n + 1 = 2 =&gt; n := 2 * n = 2
  • push 3. element =&gt; cost = <resize-cost> + <push-cost> = n + 1 = 3 =&gt; n := 2 * n = 4
  • push 4. element =&gt; cost = <push-cost> = 1 =&gt;阵列现已满了
  • push 5. element =&gt; cost = <resize-cost> + <push-cost> = n + 1 = 5 =&gt; n := 2 * n = 8
  • push 6. element =&gt; cost = <push-cost> = 1
  • push 7. element =&gt; cost = <push-cost> = 1
  • push 8. element =&gt; cost = <push-cost> = 1 =&gt;阵列现已满了
  • push 9. element =&gt; cost = <resize-cost> + <push-cost> = n + 1 = 9 =&gt; n := 2 * n = 16

...导致总费用

1 + 2 + 3 + 1 + 5 + 1 + 1 + 1 + 9 + 1 + 1 + 1 + 1 + 1 + 1 + 1...

请注意,调整大小操作总是发生在元素2^n+1上,然后是2^n-1&#34; resize-free&#34;操作。因此,我们可以将其重写为(折叠+ 1 - 左侧链)

1 + 2 + 4 + 8 + 16 + ...

(非正式地)表示每次推送操作的O(n)总费用或O(1)的摊销费用。