genPrime和genPrime2是篩法求素數的兩種實現,其實是一個思路,表示方法不同而已。
具體思路在注釋中已經含有。
#include<iostream> #include<math.h> #include<stdlib.h>using namespace std; const int MAXV = 100; //素數表範圍 bool flag[MAXV+1]; //標誌一個數是否為素數 int prime[MAXV+1]; //素數表,下標從0開始 int size=0; //素數個數 void genPrime(int max) { memset(flag, true, sizeof(flag));//首先對標籤數組進行初始化,全部設為true。 for(int i = 2; i <= max / 2; i++) { /* 從2開始,刪除2的倍數 */ if(flag[i]) { //j=i<<1等價於 j=i*2,即j是i的兩倍,而最後的j+=i,則表示下一個迴圈j是i的3倍,接著4倍。。。 //i的所有2~N倍數肯定都不是素數,因此將flag置為0,直到最後一位。 for(int j = i << 1 ; j <= max; j += i) { flag[j] = false; } } } for(int i = 2 ; i <= max; i++) { if(flag[i]) { prime[size++] = i;//儲存素數。將所有標誌位依然為1的標誌寫入素數數組中去。 } } } void genPrime2(int max) { memset(flag, true, sizeof(flag));//首先對標籤數組進行初始化,全部設為true。 int sq=sqrt((double)max)+1; //一個數 n 如果是合數,那麼它的所有的因子不超過sqrt(n) int i,j, k; for(i = 2;i<=sq; i++) { if(flag[i]) for(j=2,k=max/i+1;j<k;j++) flag[i*j] = false; //所有i的j倍都不是素數 } for( i = 2 ; i <= max; i++) { if(flag[i]) { prime[size++] = i;//儲存素數。將所有標誌位依然為1的標誌寫入素數數組中去。 } } } int main() { // genPrime(MAXV); genPrime2(MAXV); //輸出所有素數。 for(int i=0;i<size;i++) cout<<prime[i]<<" "; cout<<endl; system("pause"); return 0; } /*2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97請按任意鍵繼續. . .*/
ps:補充於2011-6-14
參考部落格:
1.http://www.cppblog.com/shyli/archive/2007/05/18/24334.html
2.http://blog.sina.com.cn/s/blog_4b5210840100cm4r.html
3.http://blog.hjenglish.com/bedford/archive/2008/10/11/401082.html
篩法其實就是以空間換時間的一個最好的證明。空間複雜度增加了,時間複雜度降低了。這個斐波那契數列求解類似,如果用遞迴,那麼時間複雜度很慢,如果將用數組儲存一個斐波那契數列,則時間複雜度降低到線性。
上面的參考部落格2有一些解釋,3則給出了具體的改進演算法。有空再研究。