/*****************************************埃拉托斯特尼筛法求素数******************************************/ *算法步骤描述: *1.列出如下这样以2开头的序列: * 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 *2.标出序列中的第一个素数,主序列变成: * 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 *3.将剩下序列中,第二项开始每隔一项划掉(2的倍数,删掉。),主序列变成: * 2 3 5 7 9 11 13 15 17 19 21 23 25 *4.如果现在这个序列中最大数小于第一个素数的平方,那么剩下的序列中所有的数都是素数,否则返回第二步。 * 本例中,因为25大于2的平方,我们返回第二步。剩下的序列中第一个素数是3,将主序列中3的倍数划掉,主序列 * 变成:2 3 5 7 11 13 17 19 23 25。我们得到的素数有:2,3。但25仍然大于3的平方,所以我们还要返回第二步。现 * 在序列中第一个素数是5,同样将序列中5的倍数划掉,主序列成了:2 3 5 7 11 13 17 19 23。我们得到的素数有:2 * 3 5 * 因为25等于5的平方,跳出循环。 *结论:2到25之间的素数是:2 3 5 7 11 13 17 19 23。 /******************************************************************************************************/ /******************************************************************************************************/ *Data:2008.07.25 *Notes: *1.采用数组的时候,有重复计算,效率不高,但本身数组的效率在取数的时候要高于链表,所以感觉比链表快一点。 *2.链表没有重复计算。 *3.本算法描述来自:http://zh.wikipedia.org/ 关键字:“埃拉托斯特尼筛法”或“Sieve Of Eratosthenes”,有所更改。 /******************************************************************************************************/ 两种方法:一种采用链表,一种采用数组 /// #include <list> #include <vector> #include <iostream> using namespace std; void SieveOfEratosthenes_1(list &lst)//链表 { list lst2; list::size_type st = lst.size(); for(list ::size_type st1 = 0;st1 < st; ++st1 ) { list::iterator it = lst.begin(); ++it; for(; it != lst.end();) { if(*it % *lst.begin() == 0) { lst.erase(it++);//如果是倍数就给删除 --st; //元素个数减少1个 } else ++it; } if((*lst.begin()) * (*lst.begin()) >= lst.back())//头元素的平方大于尾元素则链表中都为素数,停止循环 break; else { lst2.push_back(*lst.begin()); lst.pop_front();//去掉头 } } cout << "Here are the prime numbers:" << endl; for(list::iterator it2 = lst2.begin(); it2 != lst2.end(); ++it2) cout << " " << *it2; for(list::iterator it3 = lst.begin(); it3 != lst.end(); ++it3)//补上剩下的元素 { cout << " " << *it3; } } void SieveOfEratosthenes_2(int n, int data[])//数组 { int i, j; int *data2 = new int[n]; cout << "Here are the prime numbers:" << endl; for(i = 2; i < n; ++i) { if (data[i] != 0) j = data[i] << 1;//乘以2 for(; j < n; j += data[i]) { data[j] = 0; //倍数的都清零 } if(data[i] != 0 && data[i] * data[i] >= n)//头元素的平方大于尾元素则链表中都为素数,停止循环 break; } for(i = 2; i < n; ++i) { if (data[i] != 0) cout << data[i] << " ";//输出素数 } delete []data2; } int main(int argc, char* argv[]) { const int n = 100000; int *data = new int[n]; int i; list lst; data[0] = 0; data[1] = 1; for(i = 2; i < n; ++i) { data[i] = i; lst.push_back(i); } //SieveOfEratosthenes_1(lst); SieveOfEratosthenes_2(n, data); return 0; }