平摊分析的目的
算法的时间复杂度不好分析时,将总的代价平摊到每个操作上来分析总的时间复杂度的分析方法
注:都要按最坏的情况算
平摊分析的常用方法
- 聚集法:数学计算+结合具体场景更细致地分析
- 会计法:为每种操作分配不同的平摊代价,操作被执行时,若实际代价小于分配的平摊代价,则剩余的部分作为存款存到银行里;若实际代价大于分配的平摊代价,则从银行里取出“存款”来支付不足的代价。只要保证银行里的存款永远是非负的,则所有平摊代价求和就是算法的时间复杂度的上界
- 势能法:定义整个数据结构的势能函数。为每种操作分配不同的平摊代价,操作被执行时,若实际代价小于分配的平摊代价,则整个数据结构的势能增加;若实际代价大于操作的平摊代价,要用数据结构的一部分势能来支付不足的代价,整个数据结构的势能减少;只要满足n次操作后整体的势能大于初始的势能,则所有平摊代价求和就是算法时间复杂度的上界
几种常见操作的三种方法的平摊分析
栈操作的平摊分析
1.聚集法
n次操作中push的操作小于n次,pop的操作(multipop可以看成是多次pop叠加),则pop的操作要小于等于push的操作,设 T ( n ) 为 总 的 操 作 的 代 价 , 则 T ( n ) 等 于 总 的 p u s h 的 代 价 + 总 的 p o p 的 代 价 ( 包 括 m u l t i p o p ) , 所 以 T ( n ) ≤ 2 n T(n)为总的操作的代价,则T(n)等于总的push的代价+总的pop的代价(包括multipop),所以T(n) \leq 2n T(n)为总的操作的代价,则T(n)等于总的push的代价+总的pop的代价(包括multipop),所以T(n)≤2n,n次操作每次的平摊代价为 O ( 1 ) O(1) O(1)
2.会计法
为不同的操作分配不同的平摊代价
每push一次支付平摊代价2,1作为实际代价,1作为存款存放在push的数据对象上;每pop一次支付平摊代价0(multipop)看成是多次pop,pop的实际代价由数据对象上的存款来支付
n次操作中push的次数小于等于n,故平摊代价的总和小于等于2n
3.势能法
二进制计数器操作的平摊分析
问题的定义:
求初始为0的计数器上n次加1操作的时间复杂度
1.聚集法
运用数学知识,计数器的A[0]位每次+1都要翻转,A[1]位每2次+1发生一次翻转共发生
⌊
n
/
2
⌋
\lfloor n/2 \rfloor
⌊n/2⌋次 ,A[2]位每4次+1发生一次翻转共发生
⌊
n
/
4
⌋
\lfloor n/4 \rfloor
⌊n/4⌋次…
故总的代价为
∑
i
=
0
⌊
log
2
n
⌋
⌊
n
/
2
i
⌋
≤
2
n
\sum_{i=0}^{\lfloor \log_2 n \rfloor}\lfloor n/2^{i} \rfloor \leq 2n
∑i=0⌊log2n⌋⌊n/2i⌋≤2n
2.会计法
规定0-1翻转的平摊代价为2,1支付实际代价,1作为存款存到该位的1上
规定1-0翻转的平摊代价为0,用该位上的1的存款支付实际代价
对于每一个+1操作,从右往左找到第一个0,将其翻转成1,支付平摊代价2,再将这个1右边的所有1翻转成0,支付平摊代价0,故一个+1操作的总的平摊代价为2
故总的平摊代价为2n
3.势能法
注:如计数器的初始状态不是0时,总的实际代价为
故计数器中的初值与总的实际代价无关
动态表
表的扩张
表的插入操作
- 聚集法分析
- 会计法分析
注:初始表的大小为1,第一步插入的平摊代价为2
- 势能法分析
e.g如第三次插入操作需要表发生扩张,第三次操作的实际代价是表扩张后将前两个元素复制到新表的代价+将第三个元素插入到新表的代价,第三次的势能函数为2*3-4=2,则第三次操作的平摊代价为1+2=3
表的收缩
势能法分析
即将扩张或者收缩时势能函数值最大,扩张或者收缩晚后势能函数值为0