摊还分析用来评价某个数据结构的一系列操作的平均代价,有时可能某个操作的代价特别高,但总体上来看也并非那么糟糕,可以形象的理解为把高代价的操作“分摊”到其他操作上去了,要求的就是均摊后的平均代价。
摊还分析有三种常用的技术:聚合分析,核算法,势能法。
1.聚合分析
利用聚合分析,我们可以证明对于任意的
,一个包含
个操作的序列花费的总时间为
。因此,在最坏情况下,每个操作的平均代价,或称为摊还代价为
,即每个操作的时间复杂度为
。
下面讲两个简单的例子来说明。
- 栈操作
考虑一个空栈
,有三种操作:
PUSH(S,x):将对象x压入栈S中。
POP(S):将栈S的栈顶对象弹出,并返回该对象。对空栈调用POP会产生一个错误。
MULTIPOP(S,k):循环调用POP(S),弹出栈顶的k个元素(k<n,n为栈的最大容量)。
其中,第三种操作的伪代码如下:
MULTIPOP(S,k)
while not STACK-EMPTY(S) and k>0
POP(S)
k=k-1
那么,现在需要分析:执行n次栈操作最坏情况下的时间复杂度是多少?
分析:
单独看三个操作,前两个都是
的,第三个是
的。这样直观的看,最坏情况下,执行
次操作的代价是
,但这实际上是一个松的上界。因为要想达到这个上界,就要尽量多执行第三个操作,但是栈为空以后,第三个操作就什么都不干了。
我们需要对这三个操作整体分析。显然,对于一个非空的栈,可以执行的
操作的个数(包括后两个操作的所有POP)与执行了
操作的个数相当,即最多
次
。
因此,
次操作最坏情况下执行的时间复杂度为
,平均每次操作的代价是
。
在聚合分析中,我们将每个操作的摊还代价设定为平均代价,故三种操作的摊还代价都是
。
- 二进制计数器递增
考虑一个