记账方法

概述

记账方法(Accounting Method)又称银行家方法(Banker’s Method),为不同操作分配不同的摊还代价,当摊还代价超过实际代价时,差额作为信用(credit)存储在数据结构中的特定对象上;当实际代价超过摊还代价时,消费之前积累的信用来支付差额。关键约束是总信用永不为负

定义

记账方法

对每个操作 ,分配摊还代价 ,使得:

  • 时,将差额 作为信用存储在数据结构的对象中
  • 时,从已存储的信用中取出 来支付

关键约束:对于任何时刻,数据结构中存储的总信用

个操作的总代价满足:

核心性质

  1. 差异化摊还代价:与16.1 聚合分析不同,记账方法可以为不同类型的操作分配不同的摊还代价,使得分析更加精细和灵活。
  2. 信用机制:信用存储在数据结构中的具体对象上(如栈中的元素、计数器的二进制位),而非整个数据结构。这是与16.3 势能方法的关键区别。
  3. 总信用非负约束:必须始终保证 。如果某一时刻信用为负,说明摊还代价分配不足,分析失败。
  4. 直观易懂:信用存储在具体对象上的机制非常直观,类似于”预付费”概念——提前多付的钱存起来,以后需要时使用。

经典例子

栈操作

对三种栈操作分配如下摊还代价:

操作实际代价摊还代价信用变化
PUSH(S, x)12+1(存储在被压入的元素上)
POP(S)10-1(消费栈顶元素的信用)
MULTIPOP(S, k)0消费每个弹出元素的信用

验证:每个被压入的元素携带 单位信用。POPMULTIPOP 弹出元素时,恰好消费其携带的信用。因为只能弹出已被压入的元素,所以信用永远不会为负。

个操作的总摊还代价 ,每个操作摊还

二进制计数器

INCREMENT 操作中翻转的每一位分配摊还代价:

翻转类型实际代价摊还代价信用变化
(置位)12+1(存储在该位上)
(复位)10-1(消费该位的信用)

验证:每次将某位从 翻转为 时,存入 单位信用。该位将来被翻回 时,恰好消费这 单位信用。因为只有被置为 的位才会被翻回 ,所以信用始终非负。

INCREMENT 的总摊还代价 ,每次操作摊还

与聚合分析的区别

维度聚合分析记账方法
摊还代价所有操作相同不同操作可不同
分析粒度序列整体单个操作
灵活性
直观性高(直接求和)高(信用机制)
适用场景操作类型单一操作类型多样

参见