📜  计数器增量的摊销分析

📅  最后修改于: 2021-09-16 10:50:54             🧑  作者: Mango

摊销分析是指确定序列(不是单个)操作的时间平均运行时间。它与平均案例分析不同,因为在这里,我们不假设数据以平均(不是很糟糕)的方式排列,就像我们为快速排序的平均案例分析所做的那样。也就是说,摊销分析是最坏情况分析,但针对的是一系列操作而不是单个操作。它适用于由操作序列组成的方法,其中绝大多数操作是廉价的,但有些操作是昂贵的。这可以在下面实现的二进制计数器的帮助下可视化。

让我们通过在 C 中实现一个增量计数器来看看这一点。首先,让我们看看计数器增量是如何工作的。
让一个变量i包含一个值 0,我们多次执行 i++。由于在硬件上,每个操作都是以二进制形式执行的。让二进制数存储在 8 位。所以,值是 00000000。让我们增加很多次。所以,我们发现的模式是:
00000000, 00000001, 00000010, 00000011, 00000100, 00000101, 00000110, 00000111, 00001000 等等……

脚步 :
1.从最右边开始迭代并将所有 1 归零,直到找到第一个零。
2.迭代后,如果index大于或等于0,则将那个位置上的零设为一。

C++
#include 
using namespace std;
 
int main()
{
    char str[] = "10010111";
    int length = strlen(str);
    int i = length - 1;
    while (str[i] == '1') {
        str[i] = '0';
        i--;
    }
    if (i >= 0)
        str[i] = '1';
    printf("% s", str);
}


Java
import java.util.*;
 
class GFG{
 
public static void main(String args[])
{
    String st = "10010111";
    char[] str = st.toCharArray();
    int lengthh = st.length();
    int i = lengthh - 1;
     
    while (str[i] == '1')
    {
        str[i] = '0';
        i--;
    }
     
    if (i >= 0)
        str[i] = '1';
         
     System.out.print( str);
}
}
 
// This code is contributed by sanjoy_62


输出:

10011000

简单地看一下程序或算法,它的运行成本看起来与位数成正比,但实际上与位数并不成正比。让我们看看如何!

让我们假设增量操作执行了 k 次。我们看到,在每个增量中,它最右边的位都被翻转了。因此,LSB 的翻转次数为 k。因为,最右边的第二个在间隙后翻转,即以 2 次增量翻转 1 次。最右边第三个 – 1 次,以 4 次为增量。最右边的第四个 – 1 次,以 8 次为增量。因此,翻转的次数是第 2 个最右位的 k/2,第 3 个最右位的 k/4,第 4 个最右位的 k/8,依此类推……

总成本将是翻转的总数,即
C(k) = k + k/2 + k/4 + k/8 + k/16 + ……这是几何级数级数,而且,
C(k) < k + k/2 + k/4 + k/8 + k/16 + k/32 + ……直到无穷大
所以,C(k) < k/(1-1/2)
因此,C(k) < 2k
所以,C(k)/k < 2
因此,我们发现计数器递增一次的平均成本是恒定的,并且不依赖于位数。我们得出结论,计数器的增量是恒定成本操作。

参考 :

  1. http://www.cs.cornell.edu/courses/cs3110/2013sp/supplemental/recitations/rec21.html
  2. http://faculty.cs.tamu.edu/klappi/csce411-s17/csce411-amortized3.pdf

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程