总结
记账法
相当于每月领取一定的零花钱,用来支付实际费用,只要在任何时候余额不为负。那么总花费一定不超过总的零花钱。必须条件,同时也是缺点:任何时候余额不为负。
势能法
条件比记账法宽松。对于数据结构的每个状态,定义一个势能P(i),第i步操作的摊还代价记为A[i] = c[i] + P(i)-P(i-1),只要P(n) >= P(0),摊还代价就不会超过实际代价。即用前面积累起来的势能支付后面代价较大的操作。
习题编号以第三版为准。
#17.3-2 动态扩张表
对一个数据结构执行由n个操作组成的序列,当i为2的幂时,第i个操作的代价为i,否则为1。分别使用聚合分析(#17.1-3),记账法(#17.2-2)和势能法(#17.3-2)分析摊还代价。
解:实际就是动态扩张表,当容量为2的幂时,容量加倍。见课本17.4节对动态表的分析。记账法:每个操作摊还代价记为3。势能法:Potential(i) = 2*(i-maxP2)其中maxP2是不超过i的最大的2的幂,比如Potential(8)=0, Potential(9)=2, ... Potential(15)=14
#17-1 位逆序的二进制计数器
解:实际就是通过位操作实现课本中的二进制计数器,只不过自增是从左向右进行而不是从右向左。由课本中的分析可知,自增操作的平摊代价为O(1)。普通计数器代码如下:
public class Counter {
public static int increase(int n) {
int b &