“在邻接表、正反残量配对索引与精确单位成本算术下,维护 active 顶点容器及每点的当前出弧位置;检查失败后推进位置,只有该点 relabel 后才重新扫描其邻接表。这样每个高度阶段只扫描各…”
形式陈述
势能法是摊还分析的一种具体方法:为数据结构的每个状态
势增加时,本步除了支付实际工作还要预存信用;势下降时,可以取出过去的信用支付实际工作。求和后中间状态各出现一次正号和一次负号,故
若初始势为零,总摊还成本便直接控制总实际成本。单步摊还成本甚至可以为负;需要有下界的是终态势,不能让一串操作不断从无底的账户借钱。
直觉
设计势函数时,可以先问:昂贵操作会消耗哪一种积累下来的结构?若一次批量删除会清掉许多元素,就让这些元素事先各携带一点信用;若一次重建会清掉许多待处理标记,就让势记录标记数。势函数不是物理能量,而是把将来要付的工作对应到当前状态上,使昂贵操作发生时恰有足够的势下降。
例子与边界
动态数组可令势与长度、容量的差额相关,让普通追加积累的势支付下一次整体复制;具体扩缩阈值和常数摊还界集中在对应条目。二进制计数器可令势为 multipop(k) 则取势为当前元素数,弹出每个元素的实际成本由势能下降抵消。
以栈为例,先只数元素写入与删除:push 成本为
从空栈连续压入三个元素,再执行一次弹出三项,实际成本依次为
二进制计数器的完整逐位计算见摊还分析。其昂贵进位会消耗末尾的
非负势是方便的充分条件,并非唯一合法选择。更一般地,只要所有可能终态满足
推论与应用
势能法建立在摊还分析与状态上的势函数之上。先让势函数表达需要长期维护的不变量,再逐类核对操作如何改变它,便能系统地设计证明并界定任意长操作序列的总成本,而不是只解释某一个昂贵步骤。
伸展树把辅助树形状编码进势,Fibonacci 堆用根数与标记节点数为延迟合并和级联切断记账;两页分别给出具体势函数,本页不重复其旋转或堆操作。栈的批量弹出、动态数组和并查集也使用同一望远镜机制,会计法则可视为把总势拆成存放在各对象上的 credits。这样的摊还结论控制操作序列总成本,却不承诺每次操作的尾延迟。
算法分析中的“势”还有别的量词。竞争分析常令势比较在线算法与离线最优的两个状态,用单步不等式累积竞争比;乘法权重更新与Hedge跟踪总权重或对数配分函数,以界定累计 regret。它们都利用势的增量,却不把真实数据结构操作成本重新分摊,不能因此统称为摊还时间复杂度。
参考资料
- Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein, Introduction to Algorithms, 4th ed., MIT Press, 2022,§16.3:势能法与摊还成本。
- Cornell University, CS 3110 Lecture 20: Amortized Analysis, Fall 2010,“Potential (Physicist’s) Method”:初始势、非负势与望远镜求和。