『算法』摊还分析

聚合分析 (aggregate analysis)

一个 n 个操作的序列最坏情况下花费的总时间为 T(n) T ( n ) , 则在最坏情况下, 每个操作的摊还代价为 T(n)n T ( n ) n

如栈中的 push, pop 操作都是 O(1) O ( 1 ) , 增加一个新操作 multipop,

def multipop(stk,k):
  while not stk.empty() and k>0:
    stk.pop()
    k-=1

multipop 的时间复杂度为 min(stk.size,k), 最坏情况为 O(n) O ( n ) , 则 n 个包含 push pop multipop 的操作列的最坏情况是 O(n2) O ( n 2 ) , 并不是这样, 注意到, 必须栈中有元素, 再 pop, 所以 push 操作与 pop 操作 (包含 multipop 中的 pop), 个数相当, 所以 实际上应为 O(n) O ( n ) , 每个操作的摊还代价 为 O(1) O ( 1 )

核算法 (accounting method)

对不同操作赋予不同费用 cost (称为摊还代价 ci c i ′ ), 可能多于或者少于其实际代价 ci c i

ci>ci c i ′ > c i , 将 cici c i ′ − c i ( credit) 存入数据结构中的特定对象.. 对于后续 ci<ci c i ′ < c i 时, 可以使用这些 credit 来 支付差额.. 有要求

iciici ∑ i c i ′ ⩾ ∑ i c i

如栈

op ci c i ′ ci c i
push21
pop01
multipop0min(s,k)

由核算法, 摊还代价满足要求, 所以 n 个操作总代价 O(n) O ( n ) , 每个操作摊还代价为 O(1) O ( 1 )

势能法 (potential method)

势能释放用来支付未来操作的代价, 势能是整个数据结构的, 不是特定对象的 (核算法是).

数据结构 D0 D 0 为初始状态, 依次 执行 n 个操作 opi o p i 进行势能转换 Di=opi(Di1),i=1,2,,n D i = o p i ( D i − 1 ) , i = 1 , 2 , … , n , 各操作代价为 ci c i

势函数 Φ:DiR Φ : D i → R , Φ(Di) Φ ( D i ) 即为 Di D i 的势

则第 i 个操作的摊还代价

ci=ci+Φ(Di)Φ(Di1) c i ′ = c i + Φ ( D i ) − Φ ( D i − 1 )


i=1nci=i=1nci+Φ(Dn)Φ(D0) ∑ i = 1 n c i ′ = ∑ i = 1 n c i + Φ ( D n ) − Φ ( D 0 )

如果定义一个势函数 Φ,st Φ(Di)Φ(D0) Φ , s t   Φ ( D i ) ⩾ Φ ( D 0 ) , 则总摊还代价给出了实际代价的一个上界
可以简单地以 D0,then Φ(D0)=0 D 0 为参考状态 , t h e n   Φ ( D 0 ) = 0

例如栈操作,
设空栈为 D0 D 0 , 势函数定义为栈的元素数
对于 push, Φ(Di)Φ(D0)=1 Φ ( D i ) − Φ ( D 0 ) = 1
c=c+Φ(Di)Φ(D0)=c+1=2 c ′ = c + Φ ( D i ) − Φ ( D 0 ) = c + 1 = 2

对于 multipop, Φ(Di)Φ(D0)=min(k,s) Φ ( D i ) − Φ ( D 0 ) = − m i n ( k , s )
c=cmin(k,s)=0 c ′ = c − m i n ( k , s ) = 0

同理 pop 的摊还代价也是 0, 则总摊还代价的上界 (最坏情况) 为 O(n) O ( n )

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值