使用3个堆栈实现Deque(摊还时间O(1))

时间:2014-05-10 19:43:08

标签: algorithm amortized-analysis amortization

我对于如何工作有这个问题:

使用3个堆栈实现Deque。 Deque具有以下操作:InsertHead,InsertTail,DeleteHead,DeleteTail。证明每项操作的摊余时间为O(1)。

我试过的是将问题视为河内问题。 因此,我们将堆栈称为:L(左),M(中),R(右)。

伪代码实现:

InsertHead(e):
     L.push(e);

DeleteHead(e):
     L is empty:

       while R is not empty:
          pop and insert the element to M;
       pop M;
       while M is not empty:
         pop and insert the element to R;

     L is not empty:    
       L.pop(e);

InsertTail和DeleteTail与上述实现的原理相同。 我怎样才能证明摊销时间是O(1)? 因为在L中可以有N个元素,而wile循环将采用O(n),现在如果我将N次调用deleteHead计算一个摊销时间,复杂度将不是O(n ^ 2)?

有人可以帮助我如何证明上述实施在摊销时间内采用O(1)?

Deque from 3 Stacks: DeleteHead operation of Deque

1 个答案:

答案 0 :(得分:1)

我们继续使用potential method;定义

Phi = C |L.size - R.size|

对于某个常量C,我们稍后将为其选择一个值。让Phi_t表示t操作之后的潜力。请注意,在两个堆栈的大小相等的“平衡”状态下,数据结构的电位为0。

任何时候的电势都是常数乘以每个堆栈中元素数量之差。请注意,Phi_0 = 0因此在初始化结构时电位为零。

很明显,推动操作最多可以增加C的潜力。不会 miss 的弹出操作(即相关堆栈为非空的情况)也会最多改变C的电位。这两个操作的真实成本均为1,因此它们的摊销成本为1 + C

发生弹出操作并导致 miss 时(当我们要从中弹出的堆栈为空时),对于我们尝试执行操作的实际成本为1 + 3/2 * R.sizeL弹出,反之亦然。这是因为我们将R的一半元素移至M并移回,而R的另一半元素移至L。之所以需要R是因为完成此平衡操作后,+1的最后弹出。

因此,如果我们采用L,则发生 miss 时的弹出操作将摊销成本1,因为由于重新平衡,电势从C := 3/2降低到0,然后我们可能会因重新平衡后发生的爆破而产生3/2 * R.size的额外费用。

换句话说,每个工序的摊销成本均以常数为边界。

最后,由于初始电势为0,并且电势始终为非负值,因此,根据需要,每个操作均应摊销成本O(1)。