【演算法】3.Eratosthenes篩選法與尤拉篩選法求素數
阿新 • • 發佈:2018-12-29
Eratosthenes篩法
1.原理
一個合數可以分成幾個素數的和,如果把素數(最初只知道2)的倍數全都去掉,剩下的就都是素數了
2.思路分析
- 去除0,1(既不是素數又不是合數)
- 找到佇列中最小的素數,刪除其倍數
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;
}
}
}
總結:
- Eratosthenes篩法的第一重迴圈是用來找素數,然後把素數的倍數標記,而尤拉篩法換了一個角度,第一位是找素數,但是標記的時候用的是所有數
- 尤拉篩選法在資料小的時候不如Eratosthenes篩選法快,反而是資料變大以後,兩者差距變得越來越明顯,尤拉篩選法明顯快於Eratosthenes篩選法
- 尤拉演算法是一種空間換時間的演算法
參考文章:
https://blog.csdn.net/u012102306/article/details/71407105
https://blog.csdn.net/u012313335/article/details/47663801