程序的时间复杂性

时间:2009-08-30 06:39:05

标签: c optimization sieve-of-eratosthenes

 #include<stdio.h>
 #include<time.h>

 int main()

  {

    clock_t start;
    double d;
    long int n,i,j;
    scanf("%ld",&n);
    n=100000;
    j=2;
    start=clock();
    printf("\n%ld",j);

       for(j=3;j<=n;j+=2)
       {
          for(i=3;i*i<=j;i+=2)

          if(j%i==0)
            break;

           if(i*i>j)
          printf("\n%ld",j);

        }
    d=(clock()-start)/(double)CLOCKS_PER_SEC;
    printf("\n%f",d);

}

对于上述程序,当n = 100000时,我的运行时间为0.015秒。 我还在C中实现了Eratosthenes算法的Sieve,并且在n = 100000时获得了0.046的运行时间。

我的上述算法如何比我实施的Sieve算法更快。

上述程序的时间复杂度是多少?

我的筛选实施

 #define LISTSIZE 100000    //Number of integers to sieve<br>
 #include <stdio.h>
 #include <math.h>
 #include <time.h>

int main()
{   


    clock_t start;
    double d;
    long int list[LISTSIZE],i,j;
    int listMax = (int)sqrt(LISTSIZE), primeEstimate = (int)(LISTSIZE/log(LISTSIZE));

    for(int i=0; i < LISTSIZE; i++)
        list[i] = i+2;
    start=clock();

    for(i=0; i < listMax; i++)
    {
        //If the entry has been set to 0 ('removed'), skip it
        if(list[i] > 0)
        {
            //Remove all multiples of this prime
            //Starting from the next entry in the list
            //And going up in steps of size i
            for(j = i+1; j < LISTSIZE; j++)
            {
                if((list[j] % list[i]) == 0)
                    list[j] = 0;
            }
        }
    }
    d=(clock()-start)/(double)CLOCKS_PER_SEC;

    //Output the primes
    int primesFound = 0;
    for(int i=0; i < LISTSIZE; i++)
    {
        if(list[i] > 0)
        {
            primesFound++;

            printf("%ld\n", list[i]);
        }
    }
    printf("\n%f",d);
    return 0;
}

6 个答案:

答案 0 :(得分:3)

有很多事情可能会影响您的结果。当然,我们需要查看筛选实现的代码。此外,您计算机上clock功能的分辨率是多少?如果实现不能在毫秒级别实现高精度,那么您的结果可能在测量误差范围内。

我怀疑问题出在这里:

            //Remove all multiples of this prime
            //Starting from the next entry in the list
            //And going up in steps of size i
            for(j = i+1; j < LISTSIZE; j++)
            {
                    if((list[j] % list[i]) == 0)
                            list[j] = 0;
            }

这是一种删除素数的所有倍数的糟糕方法。为什么不使用内置乘法运算符来删除倍数?这个版本应该快得多:

            //Remove all multiples of this prime
            //Starting from the next entry in the list
            //And going up in steps of size i
            for(j = list[i]; j < LISTSIZE; j+=list[i])
            {
              list[j] = 0;
            }

答案 1 :(得分:1)

  

上述程序的时间复杂度是多少?

要凭经验测量程序的时间复杂度,您需要多个数据点。为多个N值运行程序,然后绘制N与时间的关系图。您可以使用电子表格,GNUplot或方格纸和铅笔来完成此操作。您还可以使用软件和/或普通旧数学来查找适合您数据的多项式曲线。

非经验性:关于分析计算复杂性已经写了很多(并在计算机科学课上讲授)。关于computational complexity theory的维基百科文章可能为进一步阅读提供了一些起点。

答案 2 :(得分:0)

您的筛选实施不正确;这就是它如此缓慢的原因:

  • 你不应该把它变成一个数字数组,而是一个标志数组(你可能仍然使用int作为数据类型,但char也会这样做)
  • 你不应该为数组使用索引移位,但list [i]应该确定我是否是素数(而不是i + 2是否为素数)
  • 你应该用i = 2
  • 开始淘汰
  • 通过这些修改,您应该遵循1800 INFORMATION的建议,并取消所有i的倍数,循环以i为步,而不是1步

答案 3 :(得分:0)

仅为您的时间复杂性:

你有一个~LISTMAX迭代的外循环和一个最大的内循环。 LISTSIZE迭代。这意味着您的复杂性

  

O(SQRT(N)×n)的

其中n = listsize。它实际上有点低,因为内部循环每次都会减少它的计数,并且仅针对每个未知数量运行。但这很难计算。由于O-Notation提供了上限,因此O(sqrt(n)* n)应该没问题。

答案 4 :(得分:0)

这种行为很难预测,但你应该考虑到访问内存并不便宜......对于小素数来说再次计算它可能会更快。

答案 5 :(得分:0)

那些运行时间太小而无意义。系统时钟分辨率不准确到那种水平。

如何获取准确的计时信息,请在循环中运行算法。重复几千次以使运行时间达到至少一秒,然后你可以将时间除以循环次数。