您不实施摊销分析。这是一种获取更准确O
边界的技术。
您必须做的基本观察是,昂贵的操作不可能随时发生。
对于由数组支持的数据结构,该数组需要不时地调整其大小,直到它满了。这是最昂贵的操作,需要O(n)
时间。数组中的所有其他插入为O(1)
。
要确定用于插入n
项目的运行时,您可以乘以n
最昂贵的操作O(n)
,从而导致总体运行时行为为O(n^2)
。
但是,这是不准确的,因为调整大小不会经常发生。
当谈论金钱时,当您分期偿还债务并分多次付款时,您将摊销成本。
我们也可以使用该模型来考虑算法。我们只是用“金钱”代替“时间”,以避免思维导图。
数组充满长度后n
,我们可以将其大小加倍。我们需要进行以下操作:
如果我们假设分配内存和复制都在线性时间内发生,那么这将是非常昂贵的操作。但是,我们现在可以使用债务的概念并将其摊销进行分析。只有,我们将在实际偿还债务之前将其摊销。
让我们假设,一旦我们调整了数组的大小,我们的(金钱/时间)余额将回到0(即我们没有债务,也没有剩余)。
这具有以下含义:
- 插入下一个
n
项目将涵盖调整大小和复制的成本(我们已经n
使用了插槽,n
而未使用的插槽`)
现在,我们可以考虑每个插入操作需要支付的费用:
- 插入
- 分配一块内存的成本
- 将其移动到新分配的内存中的成本
现在,我们已经涵盖了分配内存,复制和插入下一个n
元素的成本。但是,我们仍然忽略了为旧n
元素分配空间并进行复制。
我们只需将旧n
元素的成本分配给新元素(尚未插入)n
:
- 分配一块内存的成本
- 将其移动到新分配的内存中的成本
总共,每个插入操作将花费5个单位。这为其自身的插入以及为其自身和旧元素之一的空间的移动和分配付出了代价。
每个插入操作仍需要花费固定的时间,但是调整大小是免费的:我们通过在每次插入上花费“更多”的时间来摊销它。
结果,插入n
元素需要O(n)
时间。
此处还介绍了其他用于摊销分析的技术。