【算法】Eratosthenes篩選法與歐拉篩選法求素數

Eratosthenes篩法

1.原理

一個合數可以分成幾個素數的和,如果把素數(最初只知道2)的倍數全都去掉,剩下的就都是素數了

2.思路分析
  1. 去除0,1(既不是素數又不是合數)
  2. 找到隊列中最小的素數,刪除其倍數

在這裏插入圖片描述

3.代碼實現(只給出了函數,未寫主函數)

用一數組存這一列數,數組的標號即爲數字,值1表示爲素數,值0表示不爲素數

void sieveofe(int p[], int n)   //將數組p[],和數組的最大範圍n,輸入
{
    int i, j;
 
    p[0] = 0;
    p[1] = 0;
    p[2] = 1;
    // 初始化
    
    for(i = 3; i <= n; i++) 
	{
        p[i++] = 1;
        p[i] = 0;
    }
    //除了2,其餘偶數都是合數,先去除偶數
    
    int max = sqrt(n);
    for(i = 3; i <= max; i++)     //只需要判斷到sqrt(n)
	{
        if(p[i])
		{
            for(j = i * i; j < n; j += i)    
                p[j] = 0;
   //進行篩選,從i*i開始,如對素數3,從3*3開始,不需要從3*2開始,因爲對素數2,2*3已經篩去
        }
    }
}

歐拉篩法

Eratosthenes篩選法雖然效率高,但是Eratosthenes篩選法做了許多無用功,一個數會被篩到好幾次, 2✖6和3✖4都將12篩去,最後的時間複雜度是O(nloglogn),對於普通素數算法而言已經非常高效了,但歐拉篩選法的時間複雜度僅僅爲O(n).

1.原理:

只需要依次篩去由素數爲因子的數,剩下的都爲素數
prime[ ] 數組中的素數是遞增的,當 i 能整除 prime[ j ] ,那麼 i*prime[ j+1 ] 這個合數肯定被 prime[ j ] 乘以某個數篩掉。因爲i中含有prime[ j ]。接下去的素數同理。所以不用篩下去了。

在滿足i%prime[ j ] == 0這個條件之前以及第一次滿足改條件時, prime[ j ] 必定是 prime[ j ]*i 的最小因子。

2.代碼實現:
const int Max = 100002;        
int Prime[Max];            //用於存素數的值
int vis[Max];              //用於判斷並存所有的素數
void prime()
{
    int num = 0;
    memset(vis,1,sizeof(vis));    //申請空間,將vis數組都賦初值1,即都爲素數 
    for(int i = 2; i <= Max; i++)
    {
        if(vis[i])
            Prime[num++] = i;     //依次存最小的素數
        for(int j = 0; j < num; j++)
        {
            if (i * Prime[j] > Max)
                break;
            vis[i * Prime[j]] = 0; //即 i*Prime[j]也不爲素數
            if (i % Prime[j] == 0)
                break;
        }
    }
}

總結:

  1. Eratosthenes篩法的第一重循環是用來找素數,然後把素數的倍數標記,而歐拉篩法換了一個角度,第一位是找素數,但是標記的時候用的是所有數
  2. 歐拉篩選法在數據小的時候不如Eratosthenes篩選法快,反而是數據變大以後,兩者差距變得越來越明顯,歐拉篩選法明顯快於Eratosthenes篩選法
  3. 歐拉算法是一種空間換時間的算法
參考文章:

https://blog.csdn.net/u012102306/article/details/71407105
https://blog.csdn.net/u012313335/article/details/47663801

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