找素数的一点思考

找素数的一点思考

2016.7.17
本文代码均由C++编写

1.经典算法

经典的素数判定算法是这样:给定一个正整数n,用2到sqrt(n)之间的所有整数去除n,如果可以整除,则n不是素数,如果不可以整除,则n就是素数。所以求小于N的所有素数程序如下:

#include<iostream>
#include<cmath>
using namespace std;
#define N 1001
bool isprime(int n)
{
  int i, m, co = 0;
  m = sqrt (n);
  for(i = 1; i < m + 1; i++)
  {
    if(n % i == 0)
      co++;
    if(co > 1)
      break;
  }
  if(co == 1)
    return true;
  else
    return false;
}
int main()
{
    int i;
    for(i = 2; i < N; i++)
    {
        if(isprime(i))
            cout<<i<<endl;
    }
}

算法的时间复杂度是O(N*sqrt(N)),求解规模较小的输入,尚且没有问题。但对于规模较大的N,算法就力不从心了。有一种算法叫埃拉托斯特尼筛法(sieve of Eratosthenes),它在求解时具有相当高的效率,但是要牺牲较多的空间。

2.埃拉托斯特尼筛法

这个程序的算法是,若i为素数,则设置isprime[i] = 1;如果是合数,则设置为0。首先,将所有的数组元素设为1,表示没有已知的非素数。然后将已知为非素数(即为已知素数的倍数)的索引对应的数组元素设置为0。如果将所有较小素数的倍数都设置为0之后,a[i]仍然保持为1,则可判断它是所找的素数。

#include<iostream>
#include<cmath>
using namespace std;
#define MAX 101
bool isprime[N];
void The_Sieve_of_Eratosthenes()
{
    int i, j;
    for(i = 2; i < N; i++)
        isprime[i] = 1;
    for(i = 2; i < N; i++)
    {
        if(isprime[i])
            for(j = 2 * i; j < N; j += i)
                isprime[j] = 0;
    }
}
int main()
{
    int i;
    The_Sieve_of_Eratosthenes();
    for(i = 2; i < N; i++)
    {
        if(isprime[i])
            cout<<i<<endl;
    }
    return 0;
}

如何理解埃拉托斯特尼筛法呢?合数n一定是小于n的某个或若干素数的整数倍。反之,如果N不是任何比它小的素数的倍数,则N必然是素数。

3.经典算法改进版

经典素数判定算法中,并不需要用2到sqart(n)之间的所有整数去除n,只需要用其间的素数就够了,原因也是合数一定可以表示成若干个素数之积。算法的改进版本如下:

#include<iostream>
#include<cmath>
using namespace std;
#define N 1001
int isprime[N];
int main()
{
    int i, n, flag;
    isprime[0] = 0; //保存素数的总个数
    for (n = 2 ; n < N; n++)
    {
        flag = 1;
        for (i = 1; i <= isprime[0] && isprime[i] * isprime[i] <= n; i++)
            if (n % isprime[i] == 0)
            {
                flag = 0;
                break;
            }
        if (flag)
        {
            isprime[0]++;
            isprime[isprime[0]] = n;
            cout<<n<<endl;
        }
    }
    return 0;
}

此算法相比于普通经典算法,可谓是用空间换时间。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章