我对于如何工作有这个问题:
使用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)?
答案 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.size
从L
弹出,反之亦然。这是因为我们将R的一半元素移至M并移回,而R的另一半元素移至L。之所以需要R
是因为完成此平衡操作后,+1
的最后弹出。
因此,如果我们采用L
,则发生 miss 时的弹出操作将摊销成本1,因为由于重新平衡,电势从C := 3/2
降低到0,然后我们可能会因重新平衡后发生的爆破而产生3/2 * R.size
的额外费用。
换句话说,每个工序的摊销成本均以常数为边界。
最后,由于初始电势为0,并且电势始终为非负值,因此,根据需要,每个操作均应摊销成本O(1)。