C++求素数的算法

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
求素数算法
注意:下面的代码均是以 C++编写的。
需求一:请实现一个函数,对于给定的整型参数 n,该函数能够把自然数中,小于 n 的 质数,从小到大打印出来。 比如,当 n = 10,则打印出 2357
方案 1:试除法 分析思路:首先我们了解一下素数的定义,所谓的素数指如果有一个正整数 p 只有两个
因子 1 和 p,则 p 为素数。而这里的试除即根据素数的定义,比如要判断自然数 x 是否质数, 就不断尝试小于 x 且大于 1 的自然数,只要有一个能整除,则 x 是合数;否则,x 是质数。
int main(){
int n;
//输出不大于 n 的素数
cout<<"请输入一个正整数:"<<endl;
cin>>n;
//输出所有的不大于 n 的素数
cout<<"2"<<endl;
for(int i = 3; i <= n; i += 2){
if(isPrime(i))
cout<<i<<endl;
方案 1: 分析思路:方案一的思路很简单,使用 while 循环从最小素数 2 开始遍历,通过声明一 个变量 count 统计遍历出素数个数,当 count 达到欲求的个数时停止 while 循环。在具体的 实现时,可以根据上面需求一的情况对素数的判断与遍历做一些优化。 源代码: #include <iostream> #include <cmath> using namespace std;
void prime_number(int, int);
int main(){ int m, n; cout<<"请输入一个大于 2 的整数:"<<endl; cin>>n; m = n*log(n)*1.5; prime_number(m, n); return 0;
} void prime_number(int m, int n) {
bool IsPrime(int); void AllPrime(int);
int main() { int n; //n 表示要输出 n 个最小素数
cout<<"请输入一个正整数:"<<endl; cin>>n; AllPrime(n); return 0; } //IsPrime 函数判断一个数是否为素数 bool IsPrime(int m){ if(m < 2) return false; if(m == 2) return true;
源代码: #include <iostream> using namespace std;
//定义一个判断素数函数 bool isPrime(int n) {
if(n < 2) return false;
for(int i = 2; i < n; ++i) if(n%i == 0) return false;
return true; }
int main(){
int n;
//输出不大于 n 的素数
cout<<"请输入一个正整数:"<<endl;
cin>>n;
//输出所有的不大于 n 的素数
for(int i = 2; i <= n; i++){
if(isPrime(i))
coBaidu Nhomakorabeat<<i<<endl;
}
return 0;
}
return 0;
}
方案 1 改进二:
分析思路:一些更加聪明的程序员,会发现一个问题:尝试从 3 到√x 的所有奇数,
还是有些浪费。比如要判断 101 是否质数,101 的根号取整后是 10,那么,按照上述算法,
需要尝试的奇数分别是:3,5,7,9。但是你发现没有,对 9 的尝试是多余的。不能被 3
} k = i+1; }
for(i = 0 ; i < m; i++){ if(Num[i]) cout<<i+1<<endl;
}
delete []Num; }
需求二:请实现一个函数,对于给定的整型参数 N,该函数能够从小到大,依次打印出 自然数中最小的 N 个质数。 比如,当 N = 10,则打印出 2 3 5 7 11 13 17 19 23 29
整除,必然不能被 9 整除......顺着这个思路走下去,这些程序员就会发现:其实,只要尝
试小于√x 的质数即可。而这些质数,恰好前面已经算出来了(是不是觉得很妙?)。在具
体的算法实现时,我们借助了一个单链表来存储上一次所有遍历出来的素数,顺便说一下,
这就是算法理论中经常提到的:以空间换时间。
源代码:
s->data = i; s->next = L; L = s; } judge = 0; } }
方案 2:筛选法 分析思路:估计很多人把筛法仅仅看成是一种具体的方法。其实,筛法还是一种很普适 的思想。在处理很多复杂问题的时候,都可以看到筛法的影子。那么,筛法如何求质数的, 说起来很简单: 首先,2 是公认最小的质数,所以,先把所有 2 的倍数去掉;然后剩下的那些大于 2 的 数里面,最小的是 3,所以 3 也是质数;然后把所有 3 的倍数都去掉,剩下的那些大于 3 的 数里面,最小的是 5,所以 5 也是质数......上述过程不断重复,就可以把某个范围内的合 数全都除去(就像被筛子筛掉一样),剩下的就是质数了。 聪明的程序猿会构造一个定长的布尔型容器(通常用数组)。比方说,质数的分布范围 是 1,000,000,那么就构造一个包含 1,000,000 个布尔值的数组。然后把所有元素都初始化 为 true。在筛的过程中,一旦发现某个自然数是合数,就以该自然数为下标,把对应的布 尔值改为 false。全部筛完之后,遍历数组,找到那些值为 true 的元素,把他们的下标打 印出来即可。 源代码: #include <iostream> using namespace std;
cin>>m; prime_number(m, L); return 0; }
void prime_number(int m, list *L) { int judge = 0; //用于判断是否为素数,是值为 0,否则为 1. if(m < 2) { cout<<"输出的 m 值小了,没有质数!"<<endl; return; }
}
评价:该算法的时间复杂度 O(n2), 从时间效率来说,它是效率最差的算法,也是最平庸的
算法思路。
方案 1 改进一:
分析思路:改进的角度 1:我们知道除了 2 以外,所有的素数都是奇数,所以当寻找所 有不大于 n 的素数时,不需要从 2 到 n 都要遍历。而是除了 2 以外,只需要遍历不大于 n 的所有奇数即可。
for(i =0 ; i< m; i++){
if(i == 0) Num[i] = false; else Num[i] = true; }
k = 1; while(k < m) {
for(i = k; i < m; i++) { if(Num[i]) { for(j = i+1; j < m; j++){ if((j+1) % (i+1) == 0) Num[j] = false; } break; }
if(Num[i]) { for(j = i+1; j < m; j++){ if((j+1) % (i+1) == 0) Num[j] = false; } break;
} } k = i+1; } for(i = 0 ; i < m; i++){ if(Num[i]) {
cout<<i+1<<endl; count++; } if(count == n) break; } delete []Num; }
list *p,*s; p = L; cout<<"2"<<endl; for(int i = 3; i <= m; i+=2) {
p = L; while(p !=NULL){
if(i % p->data == 0) { judge = 1; break;
} p = p->next; } if(judge == 0){ cout<<i<<endl; s = new list();
void prime_number(int m);
int main(){ int m; cout<<"请输入一个大于 2 的整数:"<<endl; cin>>m;
prime_number(m);
return 0; }
void prime_number(int m) {
int i,j,k; bool *Num; Num = new bool[m];
for(int i=3; i < sqrt(m); i+=2){ if(n % i == 0) return false;
}
return true; } //AllPrime 函数输出 n 个最小素数 void AllPrime(int n){
if(n < 1) cout<<"输入无效数字!"<<endl; if(n == 1) {
cout<<"2"<<endl; return; }
cout<<"2"<<endl; int i = 3, count = 1; while(count<n){
if(IsPrime(i)) { cout<<i<<endl; count++;
} i+=2; } }
方案 2: 分析思路: 素数定理可以给出第 n 个素数 p(n)的渐近估计:p(n)约等于 nlogn.实际上 p(n)一般不 会大于(1+15%)*nlogn.所以方案二根据这个思路先确定一个 p(n)(肯定包含 n 个素数),再 用筛选法排除 p(n)的所有合数,最后输出 n 个素数即可。 源代码: #include <iostream> #include <cmath> using namespace std;
//定义一个判断素数函数 bool isPrime (int n) {
if(n < 2) return false; if(n == 2) return true;
for(int i = 3; i < sqrt(n); i += 2) if(n%i == 0) return false;
return true; }
改进的角度 2:当我们判断一个数是否为素数时,试除时只需要从 2 到 n 的根号即可判 断是否为素数。而且除 2 以外,所有的质数都是奇数则也就肯定不会被 2 整除,这样试除的 遍历又可以不用遍历偶数。
源代码: #include <iostream> #include <cmath> using namespace std;
int i, j, k, count = 0; bool *Num; Num = new bool[m]; for(i =0 ; i< m; i++){
if(i == 0) Num[i] = false; else Num[i] = true; } k = 1; while(k < m) { for(i = k; i < m; i++) {
#include <iostream> #include <cmath> using namespace std;
class list{ public:
int data; list* next; };
void prime_number(int m, list *L); int main(){
int m; list *L; L = NULL; cout<<"请输入一个大于 2 的整数:";
相关文档
最新文档