求素数(厄拉多塞筛法、暴力枚举法)

筛选法:

首先:找出第一个素数,把他的倍数赋值为0

其次:找出其后第一个不为0的数,该数为素数,把他的倍数赋值为0

最后:重复上述步骤....

筛选法也叫厄拉多塞筛法,因为素数的倍数必然不是素数,所以把素数的倍数全置为0,用一个新的数组保存那些不为0 的数,即为素数

#include <stdio.h>
#include <malloc.h>

void PutPrimer(int n)//筛选法求素数
{
	int *arr = (int*)malloc(sizeof(int)*n);//动态申请内存
	int k=0;            //记录素数的个数
	for(int i=0;i<n;i++)//初始化数组数据,赋值为1~n
	{
		arr[i]=i+1;
	}

        //动态申请内存单独存储素数    
	//int *brr = (int*)malloc(sizeof(int)*n/2);//动态申请内存,n以内素数最多占50%且仅当n等于2
	for(int i=1;i<n;i++)			//arr[1]=2;第一个素数
	{
		if(arr[i]!=0)               //为0则为素数的倍数,不是素数
		{
			//brr[k++]=arr[i];		//该数为素数,存放在brr中
			arr[k++]=arr[i];
			for(int j=i+1;j<n;j++)	//把该数的倍数置为0
			{
				if(arr[j]%arr[i]==0)
				{
					arr[j]=0;
				}
			}
		}
	}


	for(int i=0;i<k;i++)           //打印所有素数
	{
        //printf("%d\t",brr[i]);
        printf("%d\t",arr[i]);
	}
	puts("");   //等价于printf("\n");

}

在上述代码中我们发现,数组brr[]其实可有可无,可以优化算法(避免申请brr数组时产生开销)。把每一个素数从原数组开头重新排列,用k记录素数的个数。

暴力枚举:

暴力枚举法核心在判断该数是否为素数,由素数的定义可知素数是在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数,因此可以用循环的思想,从2开始循环到n为止如果有一个因数则这个数就不是素数。

#include <stdio.h>
#include <math.h>	//动态库 -lm

void PutPrimer(int n)//打印素数,参数为0~n
{
	int j;
	for(int i=3;i<n;i++)   
	{
		//for(j=2;j<i;j++)//2,3,4,5,6,7
		for(j=2;j<=sqrt(i*1.0);j++) //O(n^1/2)    
		{
			if(i%j == 0)//能够整除,说明不是素数
			{
				break;
			}
		}
		//if(j >= i)
		if(j > sqrt(i*1.0))
		{
			printf("%d \n",i);
		}
	}

}

int main()
{
	PutPrimer(100);
	return 0;
}

同样的,在判断2~n的过程也是可以优化的。举个例子:2*2=4,1*4=4 我们可以发现每一个数分解因式后必然一个因数大于根号n,一个因数小于根号n,极端情况下类似2×2=4的情况,两个因数都等于根号n,因此可以把判断条件换成2~根号n。

发布了75 篇原创文章 · 获赞 88 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43919932/article/details/102825149