1007:素数对猜想

素数:一个数,如果只有1和它本身两个因数,那么这样的数叫做素数
合数:一个数,如果除了1和它本身还有别的因数,那么这样的数叫做合数
输入

20

输出

4

程序要实现的功能:输出不超过20的相邻且差为2的素数对的个数

大体分析
(1)找到不超过20的素数
(2)找出相邻且差值为2的素数对

具体步骤
(1)找到不超过20的素数
对于素数的存储,选择用链表结构,在不知道存储数组大小的情况下,使用链表结构能节省存储空间。

struct node{
	int data;
	node* next;
};

①生成初始链表
我们知道,2是最小的素数,那么2的倍数就是合数,即不是素数,利用这一点,生成初始链表

void passEven(node *p,int n){
	int i = 2,j;
	node *p1; 
	for(j = i + 1;j <= n;j++){
		if(j % i != 0){
			p1 = new node;
			p1->data = j;
			p1->next = NULL;
			p->next = p1;
			p = p1;		
		}	
	}
}

此时链表中的结点如下所示
在这里插入图片描述
②遍历初始链表
我们先看一组初始链表
在这里插入图片描述
发现了没,我们只要循环√n次,就可以剔除其他的合数,形成一个只有素数的链表。
遍历初始链表需要借助3个指针,p,p1,p2,比如,当p指向3的时候,p1去遍历3后面的结点,当p1指向9时在这里插入图片描述
此时p1->data % p->data == 0,所以我们要释放指针p1指向的结点,如下图所示
在这里插入图片描述
释放完结点后,p1=NULL,我们要让p1 = p2->next,然后继续遍历
在这里插入图片描述
遍历初始链表的函数为

void traverse(node *p,int n){
	node *p2,*p1;
	while(p->data < sqrt(n)){
		p2 = p->next;
		p1 = p2->next;
		p = p2; 
		while(p1){
			if(p1->data % p->data != 0){
		        p2 = p1;
				p1 = p2->next;
			}
			else{
				p2->next = p1->next;
				p1->next = NULL;
				delete p1;
				p1 = p2->next;
			}
		}
	}
}

③删除结点
执行完程序后,我们需要用delete运算符删除结点,防止结点占用自己的存储空间。

void delNode(node *p){
	node *p1;
	while(p->next != NULL){
		p1 = p->next;
		p->next = p1->next;
		p1->next = NULL;
		delete p1;
	}
	delete p;
}

(2) 找出相邻且差值为2的素数对
这一步,我们直接遍历链表找差值即可

void PrimeArray(node *p){
	int k= 0;
	node *p1;
	p1 = p->next; 
	while(p1){		
		if(p1->data - p->data == 2)
			k++;
		p = p1;
		p1 = p->next;
	}
	cout<<k<<endl;
} 

在主函数的中的调用过程如下

int main(){
	int n;
	node *head;
	
	cin>>n;
	head = new node;head->data=2;head->next=NULL;

	passEven(head,n);//生成初始链表 
	traverse(head,n);//遍历链表 
	PrimeArray(head);//素数对猜想 
	delNode(head);//释放结点 
	
} 

完整的代码如下

#include<iostream>
#include<cmath>
using namespace std;
struct node{
	int data;
	node* next;
};

//过滤掉2的倍数,生成链表
void passEven(node *p,int n){
	int i = 2,j;
	node *p1; 
	for(j = i + 1;j <= n;j++){
		if(j % i != 0){
			p1 = new node;
			p1->data = j;
			p1->next = NULL;
			p->next = p1;
			p = p1;		
		}	
	}
}
//遍历结点
void traverse(node *p,int n){
	node *p2,*p1;
	while(p->data < sqrt(n)){
		p2 = p->next;
		p1 = p2->next;
		p = p2; 
		while(p1){
			if(p1->data % p->data != 0){
		        p2 = p1;
				p1 = p2->next;
			}
			else{
				p2->next = p1->next;
				p1->next = NULL;
				delete p1;
				p1 = p2->next;
			}
		}
	}
}
//素数对猜想 
void PrimeArray(node *p){
	int k= 0;
	node *p1;
	p1 = p->next; 
	while(p1){		
		if(p1->data - p->data == 2)
			k++;
		p = p1;
		p1 = p->next;
	}
	cout<<k<<endl;
} 


//删除结点 
void delNode(node *p){
	node *p1;
	while(p->next != NULL){
		p1 = p->next;
		p->next = p1->next;
		p1->next = NULL;
		delete p1;
	}
	delete p;
}



//创建一个结点 
int main(){
	int n;
	node *head;
	
	cin>>n;
	head = new node;head->data=2;head->next=NULL;

	passEven(head,n);//生成链表 
	traverse(head,n);//遍历链表 
	PrimeArray(head);//素数对猜想 
	delNode(head);//释放结点 
	
} 
  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值