Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 固定摊销时间_Algorithm_Complexity Theory_Big O - Fatal编程技术网

Algorithm 固定摊销时间

Algorithm 固定摊销时间,algorithm,complexity-theory,big-o,Algorithm,Complexity Theory,Big O,当谈到算法的时间复杂度时,“固定摊销时间”是什么意思?这意味着随着时间的推移,最坏情况将默认为O(1),或固定时间。一个常见的例子是动态数组。如果我们已经为一个新条目分配了内存,那么添加它将是O(1)。如果我们没有分配它,我们将通过分配,比如说,当前金额的两倍来分配。这个特殊的插入将不是O(1),而是其他东西 重要的是,算法保证在一系列操作之后,昂贵的操作将被摊销,从而使整个操作O(1) 或者更严格地说, 有一个常数c,对于 每个操作序列(也是一个以昂贵的操作结束的操作) 长度L,时间不大于 c

当谈到算法的时间复杂度时,“固定摊销时间”是什么意思?

这意味着随着时间的推移,最坏情况将默认为O(1),或固定时间。一个常见的例子是动态数组。如果我们已经为一个新条目分配了内存,那么添加它将是O(1)。如果我们没有分配它,我们将通过分配,比如说,当前金额的两倍来分配。这个特殊的插入将不是O(1),而是其他东西

重要的是,算法保证在一系列操作之后,昂贵的操作将被摊销,从而使整个操作O(1)

或者更严格地说,

有一个常数c,对于 每个操作序列(也是一个以昂贵的操作结束的操作) 长度L,时间不大于 c*L(谢谢)


用简单的术语解释摊销时间:

如果你做了一个手术,比如说一百万次,你并不真正关心这个手术的最坏情况或最好情况——你关心的是当你重复这个手术一百万次时,总共花了多少时间

因此,只要“偶尔一次”足够罕见,缓慢程度足以被冲淡,那么偶尔一次操作是否非常缓慢并不重要。实质上,摊销时间是指“如果您进行了多次操作,则每次操作所用的平均时间”。摊销时间不一定是常数;您可以有线性和对数摊销时间或其他任何形式

让我们以mats的动态数组为例,您可以在其中重复添加新项目。通常添加项目需要固定的时间(即,
O(1)
)。但每次阵列满时,都会分配两倍的空间,将数据复制到新区域,然后释放旧空间。假设分配和释放以固定时间运行,此放大过程需要
O(n)
时间,其中n是数组的当前大小


所以每次放大,所需时间是上次放大的两倍。但你在做这件事之前也等了两倍的时间!因此,每次扩大的成本可以在插入中“分摊”。这意味着从长期来看,向数组中添加m个项目所花费的总时间是
O(m)
,因此摊销时间(即每次插入的时间)是
O(1)

上述解释适用于聚合分析,即在多个操作中取“平均值”的想法。 我不确定它们是如何应用于银行家方法还是物理学家的摊销分析方法

现在。我不能完全肯定正确的答案。 但这和物理学家和银行家方法的基本条件有关:

(摊余经营成本之和)>=(实际经营成本之和)

我面临的主要困难是,鉴于运营的摊余渐进成本不同于正常的渐进成本,我不确定如何评估摊余成本的重要性

也就是说,当有人给我一个摊余成本时,我知道它和正常的渐近成本不一样,那么我从摊余成本中得出什么结论呢

由于我们有一些业务被多收费,而其他业务被少收费的情况,一个假设可能是引用个别业务的摊余成本是没有意义的

例如:对于fibonacci堆,引用仅将键减少到O(1)的摊销成本是没有意义的,因为成本是通过“增加堆潜力的早期操作所做的工作”来减少的

我们可以有另一个假设,即摊余成本的原因如下:

  • 我知道这项昂贵的行动之前将有多个低成本的行动

  • 为了便于分析,我将对一些低成本的操作多收费,这样它们的渐近成本就不会改变

  • 通过这些增加的低成本操作,我可以证明昂贵的操作具有较小的渐近成本

  • 因此,我改进/减少了n个运算的代价的渐近界


  • 因此,摊余成本分析+摊余成本界限现在仅适用于昂贵的操作。廉价操作的渐近摊余成本与正常的渐近成本相同。

    在重复阅读3次后,我发现下面的维基百科解释很有用:

    资料来源:

    “动态数组

    动态数组Push操作的摊销分析

    考虑一个动态数组,它的大小随着元素的增加而增加 例如Java中的ArrayList 对于4号,将四个元素推到其上需要恒定的时间。 然而,将第五个元素推到该数组上需要更长的时间 数组必须创建一个比当前大小(8)大一倍的新数组, 将旧元素复制到新数组中,然后添加新元素 元素。接下来的三个推送操作将同样采用常量 时间,然后后续添加将需要另一个慢速 阵列大小加倍

    一般来说,如果我们将任意数量的n推到一个数组 对于大小n,我们注意到,除了 对于最后一个需要O(n)时间来执行大小倍增的 操作。因为总共有n个操作,所以我们可以取平均值 并找到用于将元素推送到动态数组上的 取:O(n/n)=O(1),恒定时间。“

    据我理解,这只是一个简单的故事:

    假设你有很多钱。 你想把它们堆在一个房间里。 而且,你有长长的手和腿,只要你现在或将来需要。 而且,你必须在一个房间里填满所有的东西,所以很容易把它锁上

    所以,你直接走到房间的尽头/角落,开始堆叠它们。 当你把它们叠在一起时,房间会慢慢地流动
    import matplotlib.pyplot as plt
    import time
    
    
    a = []
    N = 1000000
    
    totalTimeList = [0]*N
    timeForThisIterationList = [0]*N
    for i in range(1, N):
        startTime = time.time()
        a.append([0]*500) # every iteartion, we append a value(which is a list so that it takes more time)
        timeForThisIterationList[i] = time.time() - startTime
        totalTimeList[i] = totalTimeList[i-1] + timeForThisIterationList[i]
    max_1 = max(totalTimeList)
    max_2 = max(timeForThisIterationList)
    
    plt.plot(totalTimeList, label='cumulative time')
    plt.plot(timeForThisIterationList, label='time taken per append')
    plt.legend()
    plt.title('List-append time per operation showing amortised linear complexity')
    plt.show()