摊销分析?(最坏情况下的性能保证)


13

什么是摊销分析?以及它如何帮助我在程序中实现最坏情况的性能保证

我正在阅读以下技术可以帮助程序员获得最坏情况的性能保证(即,用我自己的话说:保证程序的运行时间不会超过最差转换的运行时间):

  • 随机算法(例如,在最坏的情况下,快速排序算法是二次方的,但是对输入进行随机排序可以保证其运行时间是线性的概率)
  • 操作顺序(我们的分析必须同时考虑数据和客户端执行的操作顺序)
  • 摊销分析(提供绩效保证的另一种方法是通过跟踪所有工序的总成本除以工序数来摊销成本。在这种情况下,我们可以允许一些昂贵的工序,同时保持平均成本换句话讲,通过将一部分费用分配给大量廉价操作中的每一项,我们分散了一些昂贵操作的成本)

作者提到将调整数组数据结构大小用于Stack作为如何实现摊销分析的一个示例,但我仍然不明白什么是摊销分析,以及如何实际实现(摊分分析?铸造性能保证

Answers:


14

您不实施摊销分析。这是一种获取更准确O边界的技术。

您必须做的基本观察是,昂贵的操作不可能随时发生。

对于由数组支持的数据结构,该数组需要不时地调整其大小,直到它满了。这是最昂贵的操作,需要O(n)时间。数组中的所有其他插入为O(1)

要确定用于插入n项目的运行时,您可以乘以n最昂贵的操作O(n),从而导致总体运行时行为为O(n^2)

但是,这是不准确的,因为调整大小不会经常发生。

当谈论金钱时,当您分期偿还债务并分多次付款时,您将摊销成本。

我们也可以使用该模型来考虑算法。我们只是用“金钱”代替“时间”,以避免思维导图。

数组充满长度后n,我们可以将其大小加倍。我们需要进行以下操作:

  • 分配2n内存块
  • 复制n项目

如果我们假设分配内存和复制都在线性时间内发生,那么这将是非常昂贵的操作。但是,我们现在可以使用债务的概念并将其摊销进行分析。只有,我们将在实际偿还债务之前将其摊销。
让我们假设,一旦我们调整了数组的大小,我们的(金钱/时间)余额将回到0(即我们没有债务,也没有剩余)。

这具有以下含义:

  • 插入下一个n项目将涵盖调整大小和复制的成本(我们已经n使用了插槽,n而未使用的插槽`)

现在,我们可以考虑每个插入操作需要支付的费用:

  • 插入
  • 分配一块内存的成本
  • 将其移动到新分配的内存中的成本

现在,我们已经涵盖了分配内存,复制和插入下一个n元素的成本。但是,我们仍然忽略了为旧n元素分配空间并进行复制。

我们只需将旧n元素的成本分配给新元素(尚未插入)n

  • 分配一块内存的成本
  • 将其移动到新分配的内存中的成本

总共,每个插入操作将花费5个单位。这为其自身的插入以及为其自身和旧元素之一的空间的移动和分配付出了代价。

每个插入操作仍需要花费固定的时间,但是调整大小是免费的:我们通过在每次插入上花费“更多”的时间来摊销它。

结果,插入n元素需要O(n)时间。

此处介绍了其他用于摊销分析的技术。


1

首先:它是一种用于分析程序运行时的技术,而不是算法的实现技术。

列表中提到的示例就是一个很好的例子:将单个项目追加到数组支持的数据结构中。对于每个单独的追加操作,最坏的情况是必须复制所有现有项目。这种分析太悲观了,因为如果您使用合理的大小调整策略(将大小乘以x> 1.0则不必这样做)。然后分析表明您有一个O(n ^ 2)边界-每个项目O(n)乘以n个项目-而实际运行时间仅为O(n)。

如果您对所有插入的项目(大多数不需要调整大小)的调整大小成本进行平均,则您要进行摊销分析。摊销分析得出O(n)边界,该边界与算法的实际行为相匹配。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.