分摊分析介绍

         分摊分析[1]给我的印象是大概是心理安慰,让我们放心的用,而不去担心会有什么坏的性能问题。比如C++ 的vector 动态增长,每个操作的分摊时间复杂度是O(3)。

有三种操作手法:

聚类方法

 最坏情形下,一系列操作总的代价上界除以操作个数,就是每个操作的分摊代价。
这里每个操作的分摊代价相同。
例子 二进制计数器
INC(A)
 i = 0
 while i < A.length and A[i] == 1
  A[i] = 0
  i = i + 1
 if i < A.length
  A[i] = 1
初始时A[0..k] = 0.
INC(A)最坏是O(k), n次INC最坏达到O(nk)。
但是我们注意不是每次都O(k),只是全一时才这样。
我们来数比特位翻转的次数。第0位翻转了n次,
第1位翻转了n/2次,总共< 2n。每个INC的分摊代价是O(2)。

记账方法
 每种操作类型分摊代价可能不同,高于实际代价的差值称为prepaid credit。
例子 PUSH,POP,MULTIPOP(k)的实际代价分别是1,1,min(k,s),
而赋予分摊代价分别为2,0,0。当PUSH时,消耗1,剩余的1存入该对象,当POP时,
使用该对象上存入的1。

势能方法
 把credit当成整个数据结构的势能,而不是单个树据对象的。

例1 红黑树重建的代价
 RB_Insert/RB_Delete 首先需要O(lgN)查找到key所在节点,然后只分别需要O(1)的节点插入,节点删除和旋转,但是改变颜色
最坏可能是lgN, 其他可能是多次,或零次。
定义势能函数Phi(T)=sum{w(x): x \in T}, 其中如果x是红色,或者x是黑有两个红孩子,则w(x)=0; 如果x是黑,没有红孩子,则w(x)=1; 如果x是黑,有两个红孩子,则w(x)=2。
证明:任一RB_Insert/RB_Delete后,Phi(T)至少减少一。从任意混合的插入删除序列的分摊代价是O(1)。

例2 自组织链表:
 搜索必须从链表头开始,如果在第k项找到,则代价为k。
 搜索后允许使用任何启发式方法调整链表顺序。

heuristic knowing entire access sequence.虽然我不知道这种最优方法的代价,
但是我们使用势能分析,即使预先不知道存取序列,move-to-front heuristic方法的代价不超过最优方法代价的两倍。

例3 伸展树[2]

如果想要和红黑树一样的分摊复杂度,而编码复杂度不要那么高,就用这个。


参考

[1] 算法导论第三版

[2] https://en.wikipedia.org/wiki/Splay_tree


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值