找素數的一點思考

找素數的一點思考

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;
}

此算法相比於普通經典算法,可謂是用空間換時間。

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